Merge branch 'master' into ci/api-builds
* master: (75 commits) Fix grammar Clarify the key generation step Remove misleading `ssh-dsa` markdown fixes markdown fixes Add `AbuseReport#notify` Make AbuseReportMailer responsible for knowing if it should deliver Redirect back to user profile page after abuse report Redesign the AbuseReports index Don't notify users twice if they are both project watchers and subscribers Restructure logo JS to use `setInterval` Decrease the logo sweep delay Correct the logo ID names Update CHANGELOG Merge pull request GH-9938 from huacnlee/hotfix/note_mail_with_notification Remove jquery.blockUI.js plugin rempves tests for "you have master access" text Revert "Merge branch 'rs-remove-jquery-blockui' into 'master' " removes footer message about access to project remove public field from namespace and refactoring ...
This commit is contained in:
commit
962b97d813
11
CHANGELOG
11
CHANGELOG
|
@ -1,20 +1,27 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 8.4.0 (unreleased)
|
||||
- Expire view caches when application settings change (e.g. Gravatar disabled) (Stan Hu)
|
||||
- Don't notify users twice if they are both project watchers and subscribers (Stan Hu)
|
||||
- Implement new UI for group page
|
||||
- Implement search inside emoji picker
|
||||
- Add API support for looking up a user by username (Stan Hu)
|
||||
- Add project permissions to all project API endpoints (Stan Hu)
|
||||
- Only allow group/project members to mention `@all`
|
||||
- Expose Git's version in the admin area
|
||||
- Expose Git's version in the admin area (Trey Davis)
|
||||
- Add "Frequently used" category to emoji picker
|
||||
- Add CAS support (tduehr)
|
||||
- Add link to merge request on build detail page
|
||||
- Revert back upvote and downvote button to the issue and MR pages
|
||||
- Enable "Add key" button when user fills in a proper key (Stan Hu)
|
||||
- Swap position of Assignee and Author selector on Issuables (Zeger-Jan van de Weg)
|
||||
- Add system hook messages for project rename and transfer (Steve Norman)
|
||||
- Fix version check image in Safari
|
||||
- Show 'All' tab by default in the builds page
|
||||
- Fix API project lookups when querying with a namespace with dots (Stan Hu)
|
||||
|
||||
v 8.3.3 (unreleased)
|
||||
- Fix project transfer e-mail sending incorrect paths in e-mail notification (Stan Hu)
|
||||
- Enable "Add key" button when user fills in a proper key (Stan Hu)
|
||||
|
||||
v 8.3.2
|
||||
- Disable --follow in `git log` to avoid loading duplicate commit data in infinite scroll (Stan Hu)
|
||||
|
|
6
Gemfile
6
Gemfile
|
@ -169,10 +169,10 @@ gem 'asana', '~> 0.4.0'
|
|||
gem 'ruby-fogbugz', '~> 0.2.1'
|
||||
|
||||
# d3
|
||||
gem 'd3_rails', '~> 3.5.5'
|
||||
gem 'd3_rails', '~> 3.5.0'
|
||||
|
||||
#cal-heatmap
|
||||
gem "cal-heatmap-rails", "~> 0.0.1"
|
||||
gem 'cal-heatmap-rails', '~> 3.5.0'
|
||||
|
||||
# underscore-rails
|
||||
gem "underscore-rails", "~> 1.8.0"
|
||||
|
@ -200,7 +200,7 @@ gem 'turbolinks', '~> 2.5.0'
|
|||
gem 'jquery-turbolinks', '~> 2.1.0'
|
||||
|
||||
gem 'addressable', '~> 2.3.8'
|
||||
gem 'bootstrap-sass', '~> 3.0'
|
||||
gem 'bootstrap-sass', '~> 3.3.0'
|
||||
gem 'font-awesome-rails', '~> 4.2'
|
||||
gem 'gitlab_emoji', '~> 0.2.0'
|
||||
gem 'gon', '~> 6.0.1'
|
||||
|
|
18
Gemfile.lock
18
Gemfile.lock
|
@ -49,7 +49,7 @@ GEM
|
|||
addressable (2.3.8)
|
||||
after_commit_queue (1.3.0)
|
||||
activerecord (>= 3.0)
|
||||
allocations (1.0.1)
|
||||
allocations (1.0.3)
|
||||
annotate (2.6.10)
|
||||
activerecord (>= 3.2, <= 4.3)
|
||||
rake (~> 10.4)
|
||||
|
@ -66,7 +66,7 @@ GEM
|
|||
attr_encrypted (1.3.4)
|
||||
encryptor (>= 1.3.0)
|
||||
attr_required (1.0.0)
|
||||
autoprefixer-rails (6.1.2)
|
||||
autoprefixer-rails (6.2.3)
|
||||
execjs
|
||||
json
|
||||
awesome_print (1.2.0)
|
||||
|
@ -82,9 +82,9 @@ GEM
|
|||
erubis (>= 2.6.6)
|
||||
binding_of_caller (0.7.2)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bootstrap-sass (3.3.5)
|
||||
autoprefixer-rails (>= 5.0.0.1)
|
||||
sass (>= 3.2.19)
|
||||
bootstrap-sass (3.3.6)
|
||||
autoprefixer-rails (>= 5.2.1)
|
||||
sass (>= 3.3.4)
|
||||
brakeman (3.1.4)
|
||||
erubis (~> 2.6)
|
||||
fastercsv (~> 1.5)
|
||||
|
@ -106,7 +106,7 @@ GEM
|
|||
bundler (~> 1.2)
|
||||
thor (~> 0.18)
|
||||
byebug (8.2.1)
|
||||
cal-heatmap-rails (0.0.1)
|
||||
cal-heatmap-rails (3.5.1)
|
||||
capybara (2.4.4)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
|
@ -843,13 +843,13 @@ DEPENDENCIES
|
|||
benchmark-ips
|
||||
better_errors (~> 1.0.1)
|
||||
binding_of_caller (~> 0.7.2)
|
||||
bootstrap-sass (~> 3.0)
|
||||
bootstrap-sass (~> 3.3.0)
|
||||
brakeman (~> 3.1.0)
|
||||
browser (~> 1.0.0)
|
||||
bullet
|
||||
bundler-audit
|
||||
byebug
|
||||
cal-heatmap-rails (~> 0.0.1)
|
||||
cal-heatmap-rails (~> 3.5.0)
|
||||
capybara (~> 2.4.0)
|
||||
capybara-screenshot (~> 1.0.0)
|
||||
carrierwave (~> 0.9.0)
|
||||
|
@ -859,7 +859,7 @@ DEPENDENCIES
|
|||
connection_pool (~> 2.0)
|
||||
coveralls (~> 0.8.2)
|
||||
creole (~> 0.5.0)
|
||||
d3_rails (~> 3.5.5)
|
||||
d3_rails (~> 3.5.0)
|
||||
database_cleaner (~> 1.4.0)
|
||||
default_value_for (~> 3.0.0)
|
||||
devise (~> 3.5.3)
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2011-2015 GitLab B.V.
|
||||
Copyright (c) 2011-2016 GitLab B.V.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
#= require jquery.cookie
|
||||
#= require jquery.endless-scroll
|
||||
#= require jquery.highlight
|
||||
#= require jquery.history
|
||||
#= require jquery.waitforimages
|
||||
#= require jquery.atwho
|
||||
#= require jquery.scrollTo
|
||||
#= require jquery.blockUI
|
||||
#= require jquery.turbolinks
|
||||
#= require d3
|
||||
#= require cal-heatmap
|
||||
#= require turbolinks
|
||||
#= require autosave
|
||||
#= require bootstrap
|
||||
|
@ -27,7 +27,6 @@
|
|||
#= require branch-graph
|
||||
#= require ace/ace
|
||||
#= require ace/ext-searchbox
|
||||
#= require d3
|
||||
#= require underscore
|
||||
#= require nprogress
|
||||
#= require nprogress-turbolinks
|
||||
|
@ -39,7 +38,6 @@
|
|||
#= require shortcuts_dashboard_navigation
|
||||
#= require shortcuts_issuable
|
||||
#= require shortcuts_network
|
||||
#= require cal-heatmap
|
||||
#= require jquery.nicescroll.min
|
||||
#= require_tree .
|
||||
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
class @Calendar
|
||||
options =
|
||||
month: "short"
|
||||
day: "numeric"
|
||||
year: "numeric"
|
||||
|
||||
constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
|
||||
cal = new CalHeatMap()
|
||||
cal.init
|
||||
|
|
|
@ -15,13 +15,6 @@
|
|||
$(this).html totalIssues + 1
|
||||
else
|
||||
$(this).html totalIssues - 1
|
||||
$("body").on "click", ".issues-other-filters .dropdown-menu a", ->
|
||||
$('.issues-list').block(
|
||||
message: null,
|
||||
overlayCSS:
|
||||
backgroundColor: '#DDD'
|
||||
opacity: .4
|
||||
)
|
||||
|
||||
reload: ->
|
||||
Issues.initSelects()
|
||||
|
@ -54,7 +47,7 @@
|
|||
form = $("#issue_search_form")
|
||||
search = $("#issue_search").val()
|
||||
$('.issues-holder').css("opacity", '0.5')
|
||||
issues_url = form.attr('action') + '? '+ form.serialize()
|
||||
issues_url = form.attr('action') + '?' + form.serialize()
|
||||
|
||||
$.ajax
|
||||
type: "GET"
|
||||
|
@ -65,7 +58,7 @@
|
|||
success: (data) ->
|
||||
$('.issues-holder').html(data.html)
|
||||
# Change url so if user reload a page - search results are saved
|
||||
History.replaceState {page: issues_url}, document.title, issues_url
|
||||
history.replaceState {page: issues_url}, document.title, issues_url
|
||||
Issues.reload()
|
||||
dataType: "json"
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
NProgress.configure(showSpinner: false)
|
||||
|
||||
defaultClass = 'tanuki-shape'
|
||||
pieces = [
|
||||
'path#tanuki-right-cheek',
|
||||
'path#tanuki-right-eye, path#tanuki-right-ear',
|
||||
'path#tanuki-nose',
|
||||
'path#tanuki-left-eye, path#tanuki-left-ear',
|
||||
'path#tanuki-left-cheek',
|
||||
]
|
||||
pieceIndex = 0
|
||||
firstPiece = pieces[0]
|
||||
|
||||
currentTimer = null
|
||||
delay = 150
|
||||
|
||||
clearHighlights = ->
|
||||
$(".#{defaultClass}.highlight").attr('class', defaultClass)
|
||||
|
||||
start = ->
|
||||
clearHighlights()
|
||||
pieceIndex = 0
|
||||
pieces.reverse() unless pieces[0] == firstPiece
|
||||
currentTimer = setInterval(work, delay)
|
||||
|
||||
stop = ->
|
||||
clearInterval(currentTimer)
|
||||
clearHighlights()
|
||||
|
||||
work = ->
|
||||
clearHighlights()
|
||||
$(pieces[pieceIndex]).attr('class', "#{defaultClass} highlight")
|
||||
|
||||
# If we hit the last piece, reset the index and then reverse the array to
|
||||
# get a nice back-and-forth sweeping look
|
||||
if pieceIndex == pieces.length - 1
|
||||
pieceIndex = 0
|
||||
pieces.reverse()
|
||||
else
|
||||
pieceIndex++
|
||||
|
||||
$(document).on('page:fetch', start)
|
||||
$(document).on('page:change', stop)
|
|
@ -16,7 +16,7 @@
|
|||
form = $("#issue_search_form")
|
||||
search = $("#issue_search").val()
|
||||
$('.merge-requests-holder').css("opacity", '0.5')
|
||||
issues_url = form.attr('action') + '? '+ form.serialize()
|
||||
issues_url = form.attr('action') + '?' + form.serialize()
|
||||
|
||||
$.ajax
|
||||
type: "GET"
|
||||
|
@ -27,7 +27,7 @@
|
|||
success: (data) ->
|
||||
$('.merge-requests-holder').html(data.html)
|
||||
# Change url so if user reload a page - search results are saved
|
||||
History.replaceState {page: issues_url}, document.title, issues_url
|
||||
history.replaceState {page: issues_url}, document.title, issues_url
|
||||
MergeRequests.reload()
|
||||
dataType: "json"
|
||||
|
||||
|
|
|
@ -19,38 +19,33 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This overwrites the default values of the cal-heatmap gem
|
||||
*/
|
||||
.calendar {
|
||||
.qi {
|
||||
background-color: #999;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.q1 {
|
||||
background-color: #dae289;
|
||||
fill: #ededed;
|
||||
fill: #ededed !important;
|
||||
}
|
||||
|
||||
.q2 {
|
||||
background-color: #cedb9c;
|
||||
fill: #ACD5F2;
|
||||
fill: #ACD5F2 !important;
|
||||
}
|
||||
|
||||
.q3 {
|
||||
background-color: #b5cf6b;
|
||||
fill: #7FA8D1;
|
||||
fill: #7FA8D1 !important;
|
||||
}
|
||||
|
||||
.q4 {
|
||||
background-color: #637939;
|
||||
fill: #49729B;
|
||||
fill: #49729B !important;
|
||||
}
|
||||
|
||||
.q5 {
|
||||
background-color: #3b6427;
|
||||
fill: #254E77;
|
||||
fill: #254E77 !important;
|
||||
}
|
||||
|
||||
.domain-background {
|
||||
|
@ -59,32 +54,7 @@
|
|||
}
|
||||
|
||||
.ch-tooltip {
|
||||
position: absolute;
|
||||
display: none;
|
||||
margin-top: 22px;
|
||||
margin-left: 1px;
|
||||
font-size: 13px;
|
||||
padding: 3px;
|
||||
font-weight: 550;
|
||||
background-color: #222;
|
||||
span {
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
visibility: hidden;
|
||||
border-radius: 10px;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -8px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 8px solid #000000;
|
||||
border-right: 8px solid transparent;
|
||||
border-left: 8px solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
.tanuki-shape {
|
||||
transition: all 0.8s;
|
||||
|
||||
&:hover {
|
||||
&:hover, &.highlight {
|
||||
fill: rgb(255, 255, 255);
|
||||
transition: all 0.1s;
|
||||
}
|
||||
|
|
|
@ -54,17 +54,17 @@
|
|||
|
||||
h3 {
|
||||
margin: 24px 0 12px 0;
|
||||
font-size: 1.25em;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 24px 0 12px 0;
|
||||
font-size: 1.1em;
|
||||
font-size: 0.98em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 24px 0 12px 0;
|
||||
font-size: 1em;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
|
|
|
@ -26,6 +26,13 @@
|
|||
}
|
||||
|
||||
.project-home-panel {
|
||||
|
||||
.cover-controls {
|
||||
.project-settings-dropdown {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.project-identicon-holder {
|
||||
margin-bottom: 16px;
|
||||
|
||||
|
|
|
@ -9,12 +9,10 @@ class AbuseReportsController < ApplicationController
|
|||
@abuse_report.reporter = current_user
|
||||
|
||||
if @abuse_report.save
|
||||
if current_application_settings.admin_notification_email.present?
|
||||
AbuseReportMailer.notify(@abuse_report.id).deliver_later
|
||||
end
|
||||
@abuse_report.notify
|
||||
|
||||
message = "Thank you for your report. A GitLab administrator will look into it shortly."
|
||||
redirect_to root_path, notice: message
|
||||
redirect_to @abuse_report.user, notice: message
|
||||
else
|
||||
render :new
|
||||
end
|
||||
|
@ -23,6 +21,9 @@ class AbuseReportsController < ApplicationController
|
|||
private
|
||||
|
||||
def report_params
|
||||
params.require(:abuse_report).permit(:user_id, :message)
|
||||
params.require(:abuse_report).permit(%i(
|
||||
message
|
||||
user_id
|
||||
))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,12 +5,12 @@ class Admin::BuildsController < Admin::ApplicationController
|
|||
@builds = @all_builds.order('created_at DESC')
|
||||
@builds =
|
||||
case @scope
|
||||
when 'all'
|
||||
@builds
|
||||
when 'running'
|
||||
@builds.running_or_pending.reverse_order
|
||||
when 'finished'
|
||||
@builds.finished
|
||||
else
|
||||
@builds.running_or_pending.reverse_order
|
||||
@builds
|
||||
end
|
||||
@builds = @builds.page(params[:page]).per(30)
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Explore::GroupsController < Explore::ApplicationController
|
||||
def index
|
||||
@groups = GroupsFinder.new.execute(current_user)
|
||||
@groups = Group.order_id_desc
|
||||
@groups = @groups.search(params[:search]) if params[:search].present?
|
||||
@groups = @groups.sort(@sort = params[:sort])
|
||||
@groups = @groups.page(params[:page]).per(PER_PAGE)
|
||||
|
|
|
@ -12,12 +12,12 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
@builds = @all_builds.order('created_at DESC')
|
||||
@builds =
|
||||
case @scope
|
||||
when 'all'
|
||||
@builds
|
||||
when 'running'
|
||||
@builds.running_or_pending.reverse_order
|
||||
when 'finished'
|
||||
@builds.finished
|
||||
else
|
||||
@builds.running_or_pending.reverse_order
|
||||
@builds
|
||||
end
|
||||
@builds = @builds.page(params[:page]).per(30)
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ class UsersController < ApplicationController
|
|||
|
||||
@projects = PersonalProjectsFinder.new(@user).execute(current_user)
|
||||
|
||||
@groups = JoinedGroupsFinder.new(@user).execute(current_user)
|
||||
@groups = @user.groups.order_id_desc
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
class GroupsFinder
|
||||
# Finds the groups available to the given user.
|
||||
#
|
||||
# current_user - The user to find the groups for.
|
||||
#
|
||||
# Returns an ActiveRecord::Relation.
|
||||
def execute(current_user = nil)
|
||||
if current_user
|
||||
relation = groups_visible_to_user(current_user)
|
||||
else
|
||||
relation = public_groups
|
||||
end
|
||||
|
||||
relation.order_id_desc
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# This method returns the groups "current_user" can see.
|
||||
def groups_visible_to_user(current_user)
|
||||
base = groups_for_projects(public_and_internal_projects)
|
||||
|
||||
union = Gitlab::SQL::Union.
|
||||
new([base.select(:id), current_user.authorized_groups.select(:id)])
|
||||
|
||||
Group.where("namespaces.id IN (#{union.to_sql})")
|
||||
end
|
||||
|
||||
def public_groups
|
||||
groups_for_projects(public_projects)
|
||||
end
|
||||
|
||||
def groups_for_projects(projects)
|
||||
Group.public_and_given_groups(projects.select(:namespace_id))
|
||||
end
|
||||
|
||||
def public_projects
|
||||
Project.unscoped.public_only
|
||||
end
|
||||
|
||||
def public_and_internal_projects
|
||||
Project.unscoped.public_and_internal_only
|
||||
end
|
||||
end
|
|
@ -1,49 +0,0 @@
|
|||
# Class for finding the groups a user is a member of.
|
||||
class JoinedGroupsFinder
|
||||
def initialize(user = nil)
|
||||
@user = user
|
||||
end
|
||||
|
||||
# Finds the groups of the source user, optionally limited to those visible to
|
||||
# the current user.
|
||||
#
|
||||
# current_user - If given the groups of "@user" will only include the groups
|
||||
# "current_user" can also see.
|
||||
#
|
||||
# Returns an ActiveRecord::Relation.
|
||||
def execute(current_user = nil)
|
||||
if current_user
|
||||
relation = groups_visible_to_user(current_user)
|
||||
else
|
||||
relation = public_groups
|
||||
end
|
||||
|
||||
relation.order_id_desc
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns the groups the user in "current_user" can see.
|
||||
#
|
||||
# This list includes all public/internal projects as well as the projects of
|
||||
# "@user" that "current_user" also has access to.
|
||||
def groups_visible_to_user(current_user)
|
||||
base = @user.authorized_groups.visible_to_user(current_user)
|
||||
extra = public_and_internal_groups
|
||||
union = Gitlab::SQL::Union.new([base.select(:id), extra.select(:id)])
|
||||
|
||||
Group.where("namespaces.id IN (#{union.to_sql})")
|
||||
end
|
||||
|
||||
def public_groups
|
||||
groups_for_projects(@user.authorized_projects.public_only)
|
||||
end
|
||||
|
||||
def public_and_internal_groups
|
||||
groups_for_projects(@user.authorized_projects.public_and_internal_only)
|
||||
end
|
||||
|
||||
def groups_for_projects(projects)
|
||||
@user.groups.public_and_given_groups(projects.select(:namespace_id))
|
||||
end
|
||||
end
|
|
@ -99,7 +99,7 @@ module IssuesHelper
|
|||
end
|
||||
|
||||
def emoji_icon(name, unicode = nil, aliases = [])
|
||||
unicode ||= Emoji.emoji_filename(name)
|
||||
unicode ||= Emoji.emoji_filename(name) rescue ""
|
||||
|
||||
content_tag :div, "",
|
||||
class: "icon emoji-icon emoji-#{unicode}",
|
||||
|
|
|
@ -70,7 +70,7 @@ module SearchHelper
|
|||
|
||||
# Autocomplete results for the current user's groups
|
||||
def groups_autocomplete(term, limit = 5)
|
||||
GroupsFinder.new.execute(current_user).search(term).limit(limit).map do |group|
|
||||
Group.search(term).limit(limit).map do |group|
|
||||
{
|
||||
label: "group: #{search_result_sanitize(group.name)}",
|
||||
url: group_path(group)
|
||||
|
|
|
@ -2,11 +2,19 @@ class AbuseReportMailer < BaseMailer
|
|||
include Gitlab::CurrentSettings
|
||||
|
||||
def notify(abuse_report_id)
|
||||
return unless deliverable?
|
||||
|
||||
@abuse_report = AbuseReport.find(abuse_report_id)
|
||||
|
||||
mail(
|
||||
to: current_application_settings.admin_notification_email,
|
||||
to: current_application_settings.admin_notification_email,
|
||||
subject: "#{@abuse_report.user.name} (#{@abuse_report.user.username}) was reported for abuse"
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def deliverable?
|
||||
current_application_settings.admin_notification_email.present?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -48,7 +48,7 @@ module Emails
|
|||
|
||||
yield
|
||||
|
||||
SentNotification.record(@note, recipient_id, reply_key)
|
||||
SentNotification.record_note(@note, recipient_id, reply_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -69,7 +69,7 @@ class Ability
|
|||
subject.group
|
||||
end
|
||||
|
||||
if group && group.public_profile?
|
||||
if group && group.projects.public_only.any?
|
||||
[:read_group]
|
||||
else
|
||||
[]
|
||||
|
|
|
@ -18,4 +18,10 @@ class AbuseReport < ActiveRecord::Base
|
|||
validates :user, presence: true
|
||||
validates :message, presence: true
|
||||
validates :user_id, uniqueness: true
|
||||
|
||||
def notify
|
||||
return unless self.persisted?
|
||||
|
||||
AbuseReportMailer.notify(self.id).deliver_later
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,10 +50,6 @@ class Group < Namespace
|
|||
User.reference_pattern
|
||||
end
|
||||
|
||||
def public_and_given_groups(ids)
|
||||
where('public IS TRUE OR namespaces.id IN (?)', ids)
|
||||
end
|
||||
|
||||
def visible_to_user(user)
|
||||
where(id: user.authorized_groups.select(:id).reorder(nil))
|
||||
end
|
||||
|
@ -125,10 +121,6 @@ class Group < Namespace
|
|||
end
|
||||
end
|
||||
|
||||
def public_profile?
|
||||
self.public || projects.public_only.any?
|
||||
end
|
||||
|
||||
def post_create_hook
|
||||
Gitlab::AppLogger.info("Group \"#{name}\" was created")
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ class Project < ActiveRecord::Base
|
|||
acts_as_taggable_on :tags
|
||||
|
||||
attr_accessor :new_default_branch
|
||||
attr_accessor :old_path_with_namespace
|
||||
|
||||
# Relations
|
||||
belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
|
||||
|
@ -701,6 +702,11 @@ class Project < ActiveRecord::Base
|
|||
gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
|
||||
send_move_instructions(old_path_with_namespace)
|
||||
reset_events_cache
|
||||
|
||||
@old_path_with_namespace = old_path_with_namespace
|
||||
|
||||
SystemHooksService.new.execute_hooks_for(self, :rename)
|
||||
|
||||
@repository = nil
|
||||
rescue
|
||||
# Returning false does not rollback after_* transaction but gives
|
||||
|
|
|
@ -352,10 +352,13 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def namespace_uniq
|
||||
# Return early if username already failed the first uniqueness validation
|
||||
return if self.errors[:username].include?('has already been taken')
|
||||
|
||||
namespace_name = self.username
|
||||
existing_namespace = Namespace.by_path(namespace_name)
|
||||
if existing_namespace && existing_namespace != self.namespace
|
||||
self.errors.add :username, "already exists"
|
||||
self.errors.add(:username, 'has already been taken')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -413,6 +413,7 @@ class NotificationService
|
|||
recipients = reject_unsubscribed_users(recipients, target)
|
||||
|
||||
recipients.delete(current_user)
|
||||
recipients = recipients.uniq
|
||||
|
||||
recipients
|
||||
end
|
||||
|
|
|
@ -55,6 +55,9 @@ module Projects
|
|||
# Move uploads
|
||||
Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path)
|
||||
|
||||
project.old_path_with_namespace = old_path
|
||||
|
||||
SystemHooksService.new.execute_hooks_for(project, :transfer)
|
||||
true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,8 @@ class SystemHooksService
|
|||
def build_event_data(model, event)
|
||||
data = {
|
||||
event_name: build_event_name(model, event),
|
||||
created_at: model.created_at.xmlschema
|
||||
created_at: model.created_at.xmlschema,
|
||||
updated_at: model.updated_at.xmlschema
|
||||
}
|
||||
|
||||
case model
|
||||
|
@ -34,6 +35,14 @@ class SystemHooksService
|
|||
end
|
||||
when Project
|
||||
data.merge!(project_data(model))
|
||||
|
||||
if event == :rename || event == :transfer
|
||||
data.merge!({
|
||||
old_path_with_namespace: model.old_path_with_namespace
|
||||
})
|
||||
end
|
||||
|
||||
data
|
||||
when User
|
||||
data.merge!({
|
||||
name: model.name,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
%h3.page-title Report abuse
|
||||
%p Please use this form to report users who create spam issues, comments or behave inappropriately.
|
||||
%hr
|
||||
= form_for @abuse_report, html: { class: 'form-horizontal'} do |f|
|
||||
= form_for @abuse_report, html: { class: 'form-horizontal js-requires-input'} do |f|
|
||||
= f.hidden_field :user_id
|
||||
- if @abuse_report.errors.any?
|
||||
.alert.alert-danger
|
||||
|
@ -16,7 +16,7 @@
|
|||
.form-group
|
||||
= f.label :message, class: 'control-label'
|
||||
.col-sm-10
|
||||
= f.text_area :message, class: "form-control", rows: 2, required: true
|
||||
= f.text_area :message, class: "form-control js-quick-submit", rows: 2, required: true
|
||||
.help-block
|
||||
Explain the problem with this user. If appropriate, provide a link to the relevant issue or comment.
|
||||
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
- reporter = abuse_report.reporter
|
||||
- user = abuse_report.user
|
||||
%tr
|
||||
%td
|
||||
- if reporter
|
||||
= link_to reporter.name, reporter
|
||||
- else
|
||||
(removed)
|
||||
%td
|
||||
= abuse_report.created_at.to_s(:short)
|
||||
%td
|
||||
= abuse_report.message
|
||||
%td
|
||||
- if user
|
||||
= link_to user.name, user
|
||||
= link_to user.name, [:admin, user]
|
||||
.light.small
|
||||
Joined #{time_ago_with_tooltip(user.created_at)}
|
||||
- else
|
||||
(removed)
|
||||
%td
|
||||
- if reporter
|
||||
= link_to reporter.name, [:admin, reporter]
|
||||
- else
|
||||
(removed)
|
||||
.light.small
|
||||
= time_ago_with_tooltip(abuse_report.created_at)
|
||||
%td
|
||||
= markdown(abuse_report.message.squish!, pipeline: :single_line)
|
||||
%td
|
||||
- if user
|
||||
= link_to 'Remove user & report', admin_abuse_report_path(abuse_report, remove_user: true),
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
%table.table
|
||||
%thead
|
||||
%tr
|
||||
%th Reported by
|
||||
%th Reported at
|
||||
%th Message
|
||||
%th User
|
||||
%th Reported by
|
||||
%th Message
|
||||
%th Primary action
|
||||
%th
|
||||
= render @abuse_reports
|
||||
|
|
|
@ -149,7 +149,7 @@
|
|||
.checkbox
|
||||
= f.label :shared_runners_enabled do
|
||||
= f.check_box :shared_runners_enabled
|
||||
Enable shared runners for a new projects
|
||||
Enable shared runners for new projects
|
||||
|
||||
.form-group
|
||||
= f.label :max_artifacts_size, 'Maximum artifacts size (MB)', class: 'control-label col-sm-2'
|
||||
|
|
|
@ -7,18 +7,18 @@
|
|||
%ul.center-top-menu
|
||||
%li{class: ('active' if @scope.nil?)}
|
||||
= link_to admin_builds_path do
|
||||
All
|
||||
%span.badge.js-totalbuilds-count= @all_builds.count(:id)
|
||||
|
||||
%li{class: ('active' if @scope == 'running')}
|
||||
= link_to admin_builds_path(scope: :running) do
|
||||
Running
|
||||
%span.badge.js-running-count= @all_builds.running_or_pending.count(:id)
|
||||
%span.badge.js-running-count= number_with_delimiter(@all_builds.running_or_pending.count(:id))
|
||||
|
||||
%li{class: ('active' if @scope == 'finished')}
|
||||
= link_to admin_builds_path(scope: :finished) do
|
||||
Finished
|
||||
%span.badge.js-running-count= @all_builds.finished.count(:id)
|
||||
|
||||
%li{class: ('active' if @scope == 'all')}
|
||||
= link_to admin_builds_path(scope: :all) do
|
||||
All
|
||||
%span.badge.js-totalbuilds-count= @all_builds.count(:id)
|
||||
%span.badge.js-running-count= number_with_delimiter(@all_builds.finished.count(:id))
|
||||
|
||||
.gray-content-block
|
||||
#{(@scope || 'running').capitalize} builds
|
||||
|
|
|
@ -6,35 +6,35 @@
|
|||
%p
|
||||
Forks
|
||||
%span.light.pull-right
|
||||
= ForkedProjectLink.count
|
||||
= number_with_delimiter(ForkedProjectLink.count)
|
||||
%p
|
||||
Issues
|
||||
%span.light.pull-right
|
||||
= Issue.count
|
||||
= number_with_delimiter(Issue.count)
|
||||
%p
|
||||
Merge Requests
|
||||
%span.light.pull-right
|
||||
= MergeRequest.count
|
||||
= number_with_delimiter(MergeRequest.count)
|
||||
%p
|
||||
Notes
|
||||
%span.light.pull-right
|
||||
= Note.count
|
||||
= number_with_delimiter(Note.count)
|
||||
%p
|
||||
Snippets
|
||||
%span.light.pull-right
|
||||
= Snippet.count
|
||||
= number_with_delimiter(Snippet.count)
|
||||
%p
|
||||
SSH Keys
|
||||
%span.light.pull-right
|
||||
= Key.count
|
||||
= number_with_delimiter(Key.count)
|
||||
%p
|
||||
Milestones
|
||||
%span.light.pull-right
|
||||
= Milestone.count
|
||||
= number_with_delimiter(Milestone.count)
|
||||
%p
|
||||
Active Users
|
||||
%span.light.pull-right
|
||||
= User.active.count
|
||||
= number_with_delimiter(User.active.count)
|
||||
.col-md-4
|
||||
%h4
|
||||
Features
|
||||
|
@ -99,7 +99,7 @@
|
|||
%h4 Projects
|
||||
.data
|
||||
= link_to admin_namespaces_projects_path do
|
||||
%h1= Project.count
|
||||
%h1= number_with_delimiter(Project.count)
|
||||
%hr
|
||||
= link_to('New Project', new_project_path, class: "btn btn-new")
|
||||
.col-sm-4
|
||||
|
@ -107,7 +107,7 @@
|
|||
%h4 Users
|
||||
.data
|
||||
= link_to admin_users_path do
|
||||
%h1= User.count
|
||||
%h1= number_with_delimiter(User.count)
|
||||
%hr
|
||||
= link_to 'New User', new_admin_user_path, class: "btn btn-new"
|
||||
.col-sm-4
|
||||
|
@ -115,7 +115,7 @@
|
|||
%h4 Groups
|
||||
.data
|
||||
= link_to admin_groups_path do
|
||||
%h1= Group.count
|
||||
%h1= number_with_delimiter(Group.count)
|
||||
%hr
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-new"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- page_title "Groups"
|
||||
%h3.page-title
|
||||
Groups (#{@groups.total_count})
|
||||
Groups (#{number_with_delimiter(@groups.total_count)})
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-new pull-right"
|
||||
|
||||
%p.light
|
||||
|
|
|
@ -8,27 +8,27 @@
|
|||
%li{class: "#{'active' unless params[:filter]}"}
|
||||
= link_to admin_users_path do
|
||||
Active
|
||||
%small.pull-right= User.active.count
|
||||
%small.pull-right= number_with_delimiter(User.active.count)
|
||||
%li{class: "#{'active' if params[:filter] == "admins"}"}
|
||||
= link_to admin_users_path(filter: "admins") do
|
||||
Admins
|
||||
%small.pull-right= User.admins.count
|
||||
%small.pull-right= number_with_delimiter(User.admins.count)
|
||||
%li.filter-two-factor-enabled{class: "#{'active' if params[:filter] == 'two_factor_enabled'}"}
|
||||
= link_to admin_users_path(filter: 'two_factor_enabled') do
|
||||
2FA Enabled
|
||||
%small.pull-right= User.with_two_factor.count
|
||||
%small.pull-right= number_with_delimiter(User.with_two_factor.count)
|
||||
%li.filter-two-factor-disabled{class: "#{'active' if params[:filter] == 'two_factor_disabled'}"}
|
||||
= link_to admin_users_path(filter: 'two_factor_disabled') do
|
||||
2FA Disabled
|
||||
%small.pull-right= User.without_two_factor.count
|
||||
%small.pull-right= number_with_delimiter(User.without_two_factor.count)
|
||||
%li{class: "#{'active' if params[:filter] == "blocked"}"}
|
||||
= link_to admin_users_path(filter: "blocked") do
|
||||
Blocked
|
||||
%small.pull-right= User.blocked.count
|
||||
%small.pull-right= number_with_delimiter(User.blocked.count)
|
||||
%li{class: "#{'active' if params[:filter] == "wop"}"}
|
||||
= link_to admin_users_path(filter: "wop") do
|
||||
Without projects
|
||||
%small.pull-right= User.without_projects.count
|
||||
%small.pull-right= number_with_delimiter(User.without_projects.count)
|
||||
%hr
|
||||
= form_tag admin_users_path, method: :get, class: 'form-inline' do
|
||||
.form-group
|
||||
|
@ -42,7 +42,7 @@
|
|||
%section.col-md-9
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
Users (#{@users.total_count})
|
||||
Users (#{number_with_delimiter(@users.total_count)})
|
||||
.panel-head-actions
|
||||
.dropdown.inline
|
||||
%a.dropdown-toggle.btn.btn-sm{href: '#', "data-toggle" => "dropdown"}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
.event-item-timestamp
|
||||
#{time_ago_with_tooltip(event.created_at)}
|
||||
|
||||
= cache [event, "v2.1"] do
|
||||
= cache [event, current_application_settings, "v2.1"] do
|
||||
= image_tag avatar_icon(event.author_email, 46), class: "avatar s46", alt:''
|
||||
- if event.created_project?
|
||||
= render "events/event/created_project", event: event
|
||||
|
|
|
@ -24,15 +24,6 @@
|
|||
%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-sm remove-avatar"
|
||||
|
||||
.form-group
|
||||
%hr
|
||||
= f.label :public, class: 'control-label' do
|
||||
Public
|
||||
.col-sm-10
|
||||
.checkbox
|
||||
= f.check_box :public
|
||||
%span.descr Make this group public (even if there are no public projects inside this group)
|
||||
|
||||
.form-actions
|
||||
= f.submit 'Save group', class: "btn btn-save"
|
||||
|
||||
|
|
|
@ -47,5 +47,5 @@
|
|||
= render "projects", projects: @projects
|
||||
|
||||
- else
|
||||
%p
|
||||
This group does not have public projects
|
||||
%p.center-top-menu.no-top
|
||||
No projects to show
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
%head{prefix: "og: http://ogp.me/ns#"}
|
||||
%meta{charset: "utf-8"}
|
||||
%meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'}
|
||||
%meta{name: 'referrer', content: 'origin-when-cross-origin'}
|
||||
|
||||
%meta{name: "description", content: page_description}
|
||||
|
||||
-# Open Graph - http://ogp.me/
|
||||
%meta{property: 'og:type', content: "object"}
|
||||
|
@ -20,8 +17,8 @@
|
|||
%meta{property: 'twitter:image', content: page_image}
|
||||
= page_card_meta_tags
|
||||
|
||||
- page_title "GitLab"
|
||||
%title= page_title
|
||||
%title= page_title('GitLab')
|
||||
%meta{name: "description", content: page_description}
|
||||
|
||||
= favicon_link_tag 'favicon.ico'
|
||||
|
||||
|
@ -34,6 +31,8 @@
|
|||
|
||||
= include_gon
|
||||
|
||||
- unless browser.safari?
|
||||
%meta{name: 'referrer', content: 'origin-when-cross-origin'}
|
||||
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1'}
|
||||
%meta{name: 'theme-color', content: '#474D57'}
|
||||
|
||||
|
|
|
@ -29,13 +29,13 @@
|
|||
= icon('cog fw')
|
||||
%span
|
||||
Runners
|
||||
%span.count= Ci::Runner.count(:all)
|
||||
%span.count= number_with_delimiter(Ci::Runner.count(:all))
|
||||
= nav_link path: 'builds#index' do
|
||||
= link_to admin_builds_path do
|
||||
= icon('link fw')
|
||||
%span
|
||||
Builds
|
||||
%span.count= Ci::Build.count(:all)
|
||||
%span.count= number_with_delimiter(Ci::Build.count(:all))
|
||||
= nav_link(controller: :logs) do
|
||||
= link_to admin_logs_path, title: 'Logs' do
|
||||
= icon('file-text fw')
|
||||
|
@ -80,7 +80,7 @@
|
|||
= icon('exclamation-circle fw')
|
||||
%span
|
||||
Abuse Reports
|
||||
%span.count= AbuseReport.count(:all)
|
||||
%span.count= number_with_delimiter(AbuseReport.count(:all))
|
||||
|
||||
= nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do
|
||||
= link_to admin_application_settings_path, title: 'Settings' do
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
= icon('exclamation-circle fw')
|
||||
%span
|
||||
Issues
|
||||
%span.count= current_user.assigned_issues.opened.count
|
||||
%span.count= number_with_delimiter(current_user.assigned_issues.opened.count)
|
||||
= nav_link(path: 'dashboard#merge_requests') do
|
||||
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do
|
||||
= icon('tasks fw')
|
||||
%span
|
||||
Merge Requests
|
||||
%span.count= current_user.assigned_merge_requests.opened.count
|
||||
%span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count)
|
||||
= nav_link(controller: :snippets) do
|
||||
= link_to dashboard_snippets_path, title: 'Snippets' do
|
||||
= icon('clipboard fw')
|
||||
|
|
|
@ -25,14 +25,14 @@
|
|||
%span
|
||||
Issues
|
||||
- if current_user
|
||||
%span.count= Issue.opened.of_group(@group).count
|
||||
%span.count= number_with_delimiter(Issue.opened.of_group(@group).count)
|
||||
= nav_link(path: 'groups#merge_requests') do
|
||||
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do
|
||||
= icon('tasks fw')
|
||||
%span
|
||||
Merge Requests
|
||||
- if current_user
|
||||
%span.count= MergeRequest.opened.of_group(@group).count
|
||||
%span.count= number_with_delimiter(MergeRequest.opened.of_group(@group).count)
|
||||
= nav_link(controller: [:group_members]) do
|
||||
= link_to group_group_members_path(@group), title: 'Members' do
|
||||
= icon('users fw')
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
= icon('envelope-o fw')
|
||||
%span
|
||||
Emails
|
||||
%span.count= current_user.emails.count + 1
|
||||
%span.count= number_with_delimiter(current_user.emails.count + 1)
|
||||
- unless current_user.ldap_user?
|
||||
= nav_link(controller: :passwords) do
|
||||
= link_to edit_profile_password_path, title: 'Password' do
|
||||
|
@ -45,7 +45,7 @@
|
|||
= icon('key fw')
|
||||
%span
|
||||
SSH Keys
|
||||
%span.count= current_user.keys.count
|
||||
%span.count= number_with_delimiter(current_user.keys.count)
|
||||
= nav_link(controller: :preferences) do
|
||||
= link_to profile_preferences_path, title: 'Preferences' do
|
||||
-# TODO (rspeicher): Better icon?
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
= icon('cubes fw')
|
||||
%span
|
||||
Builds
|
||||
%span.count.builds_counter= @project.builds.running_or_pending.count(:all)
|
||||
%span.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all))
|
||||
|
||||
- if project_nav_tab? :graphs
|
||||
= nav_link(controller: %w(graphs)) do
|
||||
|
@ -67,7 +67,7 @@
|
|||
%span
|
||||
Issues
|
||||
- if @project.default_issues_tracker?
|
||||
%span.count.issue_counter= @project.issues.opened.count
|
||||
%span.count.issue_counter= number_with_delimiter(@project.issues.opened.count)
|
||||
|
||||
- if project_nav_tab? :merge_requests
|
||||
= nav_link(controller: :merge_requests) do
|
||||
|
@ -75,7 +75,7 @@
|
|||
= icon('tasks fw')
|
||||
%span
|
||||
Merge Requests
|
||||
%span.count.merge_counter= @project.merge_requests.opened.count
|
||||
%span.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count)
|
||||
|
||||
- if project_nav_tab? :settings
|
||||
= nav_link(controller: [:project_members, :teams]) do
|
||||
|
|
|
@ -18,13 +18,26 @@
|
|||
= visibility_level_label(@project.visibility_level)
|
||||
|
||||
.cover-controls
|
||||
- if can?(current_user, :admin_project, @project)
|
||||
= link_to edit_project_path(@project), class: 'btn btn-gray' do
|
||||
= icon('pencil')
|
||||
- if current_user
|
||||
|
||||
= link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), class: 'btn btn-gray' do
|
||||
= icon('rss')
|
||||
- access = user_max_access_in_project(current_user.id, @project)
|
||||
- can_edit = can?(current_user, :admin_project, @project)
|
||||
- if access || can_edit
|
||||
%span.dropdown.project-settings-dropdown
|
||||
%a.dropdown-new.btn.btn-gray#project-settings-button{href: '#', 'data-toggle' => 'dropdown'}
|
||||
= icon('cog')
|
||||
= icon('angle-down')
|
||||
%ul.dropdown-menu.dropdown-menu-right
|
||||
- if can_edit
|
||||
%li
|
||||
= link_to edit_project_path(@project) do
|
||||
Edit Project
|
||||
- if access
|
||||
%li
|
||||
= link_to leave_namespace_project_project_members_path(@project.namespace, @project),
|
||||
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
|
||||
Leave Project
|
||||
|
||||
.project-repo-buttons
|
||||
.split-one.count-buttons
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
%ul.center-top-menu
|
||||
%li{class: ('active' if @scope.nil?)}
|
||||
= link_to project_builds_path(@project) do
|
||||
All
|
||||
%span.badge.js-totalbuilds-count
|
||||
= number_with_delimiter(@all_builds.count(:id))
|
||||
|
||||
%li{class: ('active' if @scope == 'running')}
|
||||
= link_to project_builds_path(@project, scope: :running) do
|
||||
Running
|
||||
%span.badge.js-running-count
|
||||
= number_with_delimiter(@all_builds.running_or_pending.count(:id))
|
||||
|
@ -21,12 +27,6 @@
|
|||
%span.badge.js-running-count
|
||||
= number_with_delimiter(@all_builds.finished.count(:id))
|
||||
|
||||
%li{class: ('active' if @scope == 'all')}
|
||||
= link_to project_builds_path(@project, scope: :all) do
|
||||
All
|
||||
%span.badge.js-totalbuilds-count
|
||||
= number_with_delimiter(@all_builds.count(:id))
|
||||
|
||||
.gray-content-block
|
||||
#{(@scope || 'running').capitalize} builds from this project
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
- note_count = notes.user.count
|
||||
|
||||
- ci_commit = project.ci_commit(commit.sha)
|
||||
- cache_key = [project.path_with_namespace, commit.id, note_count]
|
||||
- cache_key = [project.path_with_namespace, commit.id, current_application_settings, note_count]
|
||||
- cache_key.push(ci_commit.status) if ci_commit
|
||||
|
||||
= cache(cache_key) do
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
- if @issues.present?
|
||||
.issuable-filter-count
|
||||
%span.pull-right
|
||||
= @issues.total_count
|
||||
= number_with_delimiter(@issues.total_count)
|
||||
issues for this filter
|
||||
|
||||
= paginate @issues, theme: "gitlab"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
- if @merge_requests.present?
|
||||
.issuable-filter-count
|
||||
%span.pull-right
|
||||
= @merge_requests.total_count
|
||||
= number_with_delimiter(@merge_requests.total_count)
|
||||
merge requests for this filter
|
||||
|
||||
= paginate @merge_requests, theme: "gitlab"
|
||||
|
|
|
@ -68,15 +68,4 @@
|
|||
= render 'projects/last_commit', commit: @repository.commit, project: @project
|
||||
|
||||
%div{class: "project-show-#{default_project_view}"}
|
||||
= render default_project_view
|
||||
|
||||
- if current_user
|
||||
- access = user_max_access_in_project(current_user.id, @project)
|
||||
- if access
|
||||
.prepend-top-20.project-footer
|
||||
.gray-content-block.footer-block.center
|
||||
You have #{access} access to this project.
|
||||
- if @project.project_member_by_id(current_user)
|
||||
= link_to leave_namespace_project_project_members_path(@project.namespace, @project),
|
||||
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project', class: 'cred' do
|
||||
Leave this project
|
||||
= render default_project_view
|
|
@ -5,13 +5,13 @@
|
|||
<g id="Fill-1-+-Group-24">
|
||||
<g id="Group-24">
|
||||
<g id="Group">
|
||||
<path d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" id="Fill-4" fill="#E24329" class="tanuki-shape"></path>
|
||||
<path d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-8" fill="#FC6D26" class="tanuki-shape"></path>
|
||||
<path d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" id="Fill-12" fill="#FCA326" class="tanuki-shape"></path>
|
||||
<path d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" id="Fill-16" fill="#E24329" class="tanuki-shape"></path>
|
||||
<path d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-18" fill="#FC6D26" class="tanuki-shape"></path>
|
||||
<path d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" id="Fill-20" fill="#FCA326" class="tanuki-shape"></path>
|
||||
<path d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" id="Fill-22" fill="#E24329" class="tanuki-shape"></path>
|
||||
<path id="tanuki-right-ear" d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" fill="#E24329" class="tanuki-shape"></path>
|
||||
<path id="tanuki-right-cheek" d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" fill="#FCA326" class="tanuki-shape"></path>
|
||||
<path id="tanuki-right-eye" d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" fill="#FC6D26" class="tanuki-shape"></path>
|
||||
<path id="tanuki-nose" d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" fill="#E24329" class="tanuki-shape"></path>
|
||||
<path id="tanuki-left-eye" d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" fill="#FC6D26" class="tanuki-shape"></path>
|
||||
<path id="tanuki-left-cheek" d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" fill="#FCA326" class="tanuki-shape"></path>
|
||||
<path id="tanuki-left-ear" d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" fill="#E24329" class="tanuki-shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -29,14 +29,14 @@
|
|||
= check_box_tag "check_all_issues", nil, false,
|
||||
class: "check_all_issues left"
|
||||
.issues-other-filters
|
||||
.filter-item.inline
|
||||
= users_select_tag(:assignee_id, selected: params[:assignee_id],
|
||||
placeholder: 'Assignee', class: 'trigger-submit', any_user: "Any Assignee", null_user: true, first_user: true, current_user: true)
|
||||
|
||||
.filter-item.inline
|
||||
= users_select_tag(:author_id, selected: params[:author_id],
|
||||
placeholder: 'Author', class: 'trigger-submit', any_user: "Any Author", first_user: true, current_user: true)
|
||||
|
||||
.filter-item.inline
|
||||
= users_select_tag(:assignee_id, selected: params[:assignee_id],
|
||||
placeholder: 'Assignee', class: 'trigger-submit', any_user: "Any Assignee", null_user: true, first_user: true, current_user: true)
|
||||
|
||||
.filter-item.inline.milestone-filter
|
||||
= select_tag('milestone_title', projects_milestones_options,
|
||||
class: 'select2 trigger-submit', include_blank: true,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
- css_class = '' unless local_assigns[:css_class]
|
||||
- css_class += " no-description" unless project.description.present?
|
||||
%li.project-row{ class: css_class }
|
||||
= cache [project.namespace, project, controller.controller_name, controller.action_name, 'v2.2'] do
|
||||
= cache [project.namespace, project, controller.controller_name, controller.action_name, current_application_settings, 'v2.2'] do
|
||||
= link_to project_path(project), class: dom_class(project) do
|
||||
- if avatar
|
||||
.dash-project-avatar
|
||||
|
|
|
@ -152,9 +152,9 @@ Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80
|
|||
Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || ''
|
||||
Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http"
|
||||
Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil?
|
||||
Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}"
|
||||
Settings.gitlab['email_display_name'] ||= "GitLab"
|
||||
Settings.gitlab['email_reply_to'] ||= "noreply@#{Settings.gitlab.host}"
|
||||
Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings.gitlab.host}"
|
||||
Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab'
|
||||
Settings.gitlab['email_reply_to'] ||= ENV['GITLAB_EMAIL_REPLY_TO'] || "noreply@#{Settings.gitlab.host}"
|
||||
Settings.gitlab['base_url'] ||= Settings.send(:build_base_gitlab_url)
|
||||
Settings.gitlab['url'] ||= Settings.send(:build_gitlab_url)
|
||||
Settings.gitlab['user'] ||= 'git'
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
if Gitlab::Metrics.enabled?
|
||||
require 'influxdb'
|
||||
require 'socket'
|
||||
require 'connection_pool'
|
||||
require 'method_source'
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# Use this file to easily define all of your cron jobs.
|
||||
#
|
||||
# If you make changes to this file, please create also an issue on
|
||||
# https://gitlab.com/gitlab-org/omnibus-gitlab/issues . This is necessary
|
||||
# because the omnibus packages manage cron jobs using Chef instead of Whenever.
|
||||
every 1.hour do
|
||||
rake "ci:schedule_builds"
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
# Migration type: online
|
||||
class RemovePublicFromNamespace < ActiveRecord::Migration
|
||||
def change
|
||||
remove_column :namespaces, :public, :boolean
|
||||
end
|
||||
end
|
518
db/schema.rb
518
db/schema.rb
|
@ -32,44 +32,44 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
t.text "sign_in_text"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "home_page_url"
|
||||
t.integer "default_branch_protection", default: 2
|
||||
t.boolean "twitter_sharing_enabled", default: true
|
||||
t.string "home_page_url", limit: 255
|
||||
t.integer "default_branch_protection", default: 2
|
||||
t.boolean "twitter_sharing_enabled", default: true
|
||||
t.text "restricted_visibility_levels"
|
||||
t.boolean "version_check_enabled", default: true
|
||||
t.integer "max_attachment_size", default: 10, null: false
|
||||
t.boolean "version_check_enabled", default: true
|
||||
t.integer "max_attachment_size", default: 10, null: false
|
||||
t.integer "default_project_visibility"
|
||||
t.integer "default_snippet_visibility"
|
||||
t.text "restricted_signup_domains"
|
||||
t.boolean "user_oauth_applications", default: true
|
||||
t.string "after_sign_out_path"
|
||||
t.integer "session_expire_delay", default: 10080, null: false
|
||||
t.boolean "user_oauth_applications", default: true
|
||||
t.string "after_sign_out_path", limit: 255
|
||||
t.integer "session_expire_delay", default: 10080, null: false
|
||||
t.text "import_sources"
|
||||
t.text "help_page_text"
|
||||
t.string "admin_notification_email"
|
||||
t.boolean "shared_runners_enabled", default: true, null: false
|
||||
t.integer "max_artifacts_size", default: 100, null: false
|
||||
t.string "admin_notification_email", limit: 255
|
||||
t.boolean "shared_runners_enabled", default: true, null: false
|
||||
t.integer "max_artifacts_size", default: 100, null: false
|
||||
t.string "runners_registration_token"
|
||||
t.boolean "require_two_factor_authentication", default: false
|
||||
t.integer "two_factor_grace_period", default: 48
|
||||
t.boolean "metrics_enabled", default: false
|
||||
t.string "metrics_host", default: "localhost"
|
||||
t.boolean "require_two_factor_authentication", default: false
|
||||
t.integer "two_factor_grace_period", default: 48
|
||||
t.boolean "metrics_enabled", default: false
|
||||
t.string "metrics_host", default: "localhost"
|
||||
t.string "metrics_username"
|
||||
t.string "metrics_password"
|
||||
t.integer "metrics_pool_size", default: 16
|
||||
t.integer "metrics_timeout", default: 10
|
||||
t.integer "metrics_method_call_threshold", default: 10
|
||||
t.boolean "recaptcha_enabled", default: false
|
||||
t.integer "metrics_pool_size", default: 16
|
||||
t.integer "metrics_timeout", default: 10
|
||||
t.integer "metrics_method_call_threshold", default: 10
|
||||
t.boolean "recaptcha_enabled", default: false
|
||||
t.string "recaptcha_site_key"
|
||||
t.string "recaptcha_private_key"
|
||||
t.integer "metrics_port", default: 8089
|
||||
t.integer "metrics_port", default: 8089
|
||||
end
|
||||
|
||||
create_table "audit_events", force: :cascade do |t|
|
||||
t.integer "author_id", null: false
|
||||
t.string "type", null: false
|
||||
t.integer "entity_id", null: false
|
||||
t.string "entity_type", null: false
|
||||
t.integer "author_id", null: false
|
||||
t.string "type", limit: 255, null: false
|
||||
t.integer "entity_id", null: false
|
||||
t.string "entity_type", limit: 255, null: false
|
||||
t.text "details"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
|
@ -80,14 +80,14 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "audit_events", ["type"], name: "index_audit_events_on_type", using: :btree
|
||||
|
||||
create_table "broadcast_messages", force: :cascade do |t|
|
||||
t.text "message", null: false
|
||||
t.text "message", null: false
|
||||
t.datetime "starts_at"
|
||||
t.datetime "ends_at"
|
||||
t.integer "alert_type"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "color"
|
||||
t.string "font"
|
||||
t.string "color", limit: 255
|
||||
t.string "font", limit: 255
|
||||
end
|
||||
|
||||
create_table "ci_application_settings", force: :cascade do |t|
|
||||
|
@ -99,7 +99,7 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
|
||||
create_table "ci_builds", force: :cascade do |t|
|
||||
t.integer "project_id"
|
||||
t.string "status"
|
||||
t.string "status", limit: 255
|
||||
t.datetime "finished_at"
|
||||
t.text "trace"
|
||||
t.datetime "created_at"
|
||||
|
@ -110,19 +110,19 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
t.integer "commit_id"
|
||||
t.text "commands"
|
||||
t.integer "job_id"
|
||||
t.string "name"
|
||||
t.boolean "deploy", default: false
|
||||
t.string "name", limit: 255
|
||||
t.boolean "deploy", default: false
|
||||
t.text "options"
|
||||
t.boolean "allow_failure", default: false, null: false
|
||||
t.string "stage"
|
||||
t.boolean "allow_failure", default: false, null: false
|
||||
t.string "stage", limit: 255
|
||||
t.integer "trigger_request_id"
|
||||
t.integer "stage_idx"
|
||||
t.boolean "tag"
|
||||
t.string "ref"
|
||||
t.string "ref", limit: 255
|
||||
t.integer "user_id"
|
||||
t.string "type"
|
||||
t.string "target_url"
|
||||
t.string "description"
|
||||
t.string "type", limit: 255
|
||||
t.string "target_url", limit: 255
|
||||
t.string "description", limit: 255
|
||||
t.text "artifacts_file"
|
||||
t.integer "gl_project_id"
|
||||
end
|
||||
|
@ -141,13 +141,13 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
|
||||
create_table "ci_commits", force: :cascade do |t|
|
||||
t.integer "project_id"
|
||||
t.string "ref"
|
||||
t.string "sha"
|
||||
t.string "before_sha"
|
||||
t.string "ref", limit: 255
|
||||
t.string "sha", limit: 255
|
||||
t.string "before_sha", limit: 255
|
||||
t.text "push_data"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "tag", default: false
|
||||
t.boolean "tag", default: false
|
||||
t.text "yaml_errors"
|
||||
t.datetime "committed_at"
|
||||
t.integer "gl_project_id"
|
||||
|
@ -174,16 +174,16 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "ci_events", ["project_id"], name: "index_ci_events_on_project_id", using: :btree
|
||||
|
||||
create_table "ci_jobs", force: :cascade do |t|
|
||||
t.integer "project_id", null: false
|
||||
t.integer "project_id", null: false
|
||||
t.text "commands"
|
||||
t.boolean "active", default: true, null: false
|
||||
t.boolean "active", default: true, null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "name"
|
||||
t.boolean "build_branches", default: true, null: false
|
||||
t.boolean "build_tags", default: false, null: false
|
||||
t.string "job_type", default: "parallel"
|
||||
t.string "refs"
|
||||
t.string "name", limit: 255
|
||||
t.boolean "build_branches", default: true, null: false
|
||||
t.boolean "build_tags", default: false, null: false
|
||||
t.string "job_type", limit: 255, default: "parallel"
|
||||
t.string "refs", limit: 255
|
||||
t.datetime "deleted_at"
|
||||
end
|
||||
|
||||
|
@ -191,25 +191,25 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "ci_jobs", ["project_id"], name: "index_ci_jobs_on_project_id", using: :btree
|
||||
|
||||
create_table "ci_projects", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "timeout", default: 3600, null: false
|
||||
t.string "name", limit: 255
|
||||
t.integer "timeout", default: 3600, null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "token"
|
||||
t.string "default_ref"
|
||||
t.string "path"
|
||||
t.boolean "always_build", default: false, null: false
|
||||
t.string "token", limit: 255
|
||||
t.string "default_ref", limit: 255
|
||||
t.string "path", limit: 255
|
||||
t.boolean "always_build", default: false, null: false
|
||||
t.integer "polling_interval"
|
||||
t.boolean "public", default: false, null: false
|
||||
t.string "ssh_url_to_repo"
|
||||
t.boolean "public", default: false, null: false
|
||||
t.string "ssh_url_to_repo", limit: 255
|
||||
t.integer "gitlab_id"
|
||||
t.boolean "allow_git_fetch", default: true, null: false
|
||||
t.string "email_recipients", default: "", null: false
|
||||
t.boolean "email_add_pusher", default: true, null: false
|
||||
t.boolean "email_only_broken_builds", default: true, null: false
|
||||
t.string "skip_refs"
|
||||
t.string "coverage_regex"
|
||||
t.boolean "shared_runners_enabled", default: false
|
||||
t.boolean "allow_git_fetch", default: true, null: false
|
||||
t.string "email_recipients", limit: 255, default: "", null: false
|
||||
t.boolean "email_add_pusher", default: true, null: false
|
||||
t.boolean "email_only_broken_builds", default: true, null: false
|
||||
t.string "skip_refs", limit: 255
|
||||
t.string "coverage_regex", limit: 255
|
||||
t.boolean "shared_runners_enabled", default: false
|
||||
t.text "generated_yaml_config"
|
||||
end
|
||||
|
||||
|
@ -228,34 +228,34 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "ci_runner_projects", ["runner_id"], name: "index_ci_runner_projects_on_runner_id", using: :btree
|
||||
|
||||
create_table "ci_runners", force: :cascade do |t|
|
||||
t.string "token"
|
||||
t.string "token", limit: 255
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "description"
|
||||
t.string "description", limit: 255
|
||||
t.datetime "contacted_at"
|
||||
t.boolean "active", default: true, null: false
|
||||
t.boolean "is_shared", default: false
|
||||
t.string "name"
|
||||
t.string "version"
|
||||
t.string "revision"
|
||||
t.string "platform"
|
||||
t.string "architecture"
|
||||
t.boolean "active", default: true, null: false
|
||||
t.boolean "is_shared", default: false
|
||||
t.string "name", limit: 255
|
||||
t.string "version", limit: 255
|
||||
t.string "revision", limit: 255
|
||||
t.string "platform", limit: 255
|
||||
t.string "architecture", limit: 255
|
||||
end
|
||||
|
||||
create_table "ci_services", force: :cascade do |t|
|
||||
t.string "type"
|
||||
t.string "title"
|
||||
t.integer "project_id", null: false
|
||||
t.string "type", limit: 255
|
||||
t.string "title", limit: 255
|
||||
t.integer "project_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "active", default: false, null: false
|
||||
t.boolean "active", default: false, null: false
|
||||
t.text "properties"
|
||||
end
|
||||
|
||||
add_index "ci_services", ["project_id"], name: "index_ci_services_on_project_id", using: :btree
|
||||
|
||||
create_table "ci_sessions", force: :cascade do |t|
|
||||
t.string "session_id", null: false
|
||||
t.string "session_id", limit: 255, null: false
|
||||
t.text "data"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
|
@ -267,9 +267,9 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
create_table "ci_taggings", force: :cascade do |t|
|
||||
t.integer "tag_id"
|
||||
t.integer "taggable_id"
|
||||
t.string "taggable_type"
|
||||
t.string "taggable_type", limit: 255
|
||||
t.integer "tagger_id"
|
||||
t.string "tagger_type"
|
||||
t.string "tagger_type", limit: 255
|
||||
t.string "context", limit: 128
|
||||
t.datetime "created_at"
|
||||
end
|
||||
|
@ -278,8 +278,8 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "ci_taggings", ["taggable_id", "taggable_type", "context"], name: "index_ci_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree
|
||||
|
||||
create_table "ci_tags", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "taggings_count", default: 0
|
||||
t.string "name", limit: 255
|
||||
t.integer "taggings_count", default: 0
|
||||
end
|
||||
|
||||
add_index "ci_tags", ["name"], name: "index_ci_tags_on_name", unique: true, using: :btree
|
||||
|
@ -293,7 +293,7 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
end
|
||||
|
||||
create_table "ci_triggers", force: :cascade do |t|
|
||||
t.string "token"
|
||||
t.string "token", limit: 255
|
||||
t.integer "project_id"
|
||||
t.datetime "deleted_at"
|
||||
t.datetime "created_at"
|
||||
|
@ -306,19 +306,19 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
|
||||
create_table "ci_variables", force: :cascade do |t|
|
||||
t.integer "project_id"
|
||||
t.string "key"
|
||||
t.string "key", limit: 255
|
||||
t.text "value"
|
||||
t.text "encrypted_value"
|
||||
t.string "encrypted_value_salt"
|
||||
t.string "encrypted_value_iv"
|
||||
t.string "encrypted_value_salt", limit: 255
|
||||
t.string "encrypted_value_iv", limit: 255
|
||||
t.integer "gl_project_id"
|
||||
end
|
||||
|
||||
add_index "ci_variables", ["gl_project_id"], name: "index_ci_variables_on_gl_project_id", using: :btree
|
||||
|
||||
create_table "ci_web_hooks", force: :cascade do |t|
|
||||
t.string "url", null: false
|
||||
t.integer "project_id", null: false
|
||||
t.string "url", limit: 255, null: false
|
||||
t.integer "project_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
@ -333,8 +333,8 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "deploy_keys_projects", ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree
|
||||
|
||||
create_table "emails", force: :cascade do |t|
|
||||
t.integer "user_id", null: false
|
||||
t.string "email", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.string "email", limit: 255, null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
@ -343,9 +343,9 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "emails", ["user_id"], name: "index_emails_on_user_id", using: :btree
|
||||
|
||||
create_table "events", force: :cascade do |t|
|
||||
t.string "target_type"
|
||||
t.string "target_type", limit: 255
|
||||
t.integer "target_id"
|
||||
t.string "title"
|
||||
t.string "title", limit: 255
|
||||
t.text "data"
|
||||
t.integer "project_id"
|
||||
t.datetime "created_at"
|
||||
|
@ -371,8 +371,8 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
|
||||
|
||||
create_table "identities", force: :cascade do |t|
|
||||
t.string "extern_uid"
|
||||
t.string "provider"
|
||||
t.string "extern_uid", limit: 255
|
||||
t.string "provider", limit: 255
|
||||
t.integer "user_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
|
@ -382,17 +382,17 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree
|
||||
|
||||
create_table "issues", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.string "title", limit: 255
|
||||
t.integer "assignee_id"
|
||||
t.integer "author_id"
|
||||
t.integer "project_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "position", default: 0
|
||||
t.string "branch_name"
|
||||
t.integer "position", default: 0
|
||||
t.string "branch_name", limit: 255
|
||||
t.text "description"
|
||||
t.integer "milestone_id"
|
||||
t.string "state"
|
||||
t.string "state", limit: 255
|
||||
t.integer "iid"
|
||||
t.integer "updated_by_id"
|
||||
end
|
||||
|
@ -412,10 +412,10 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.text "key"
|
||||
t.string "title"
|
||||
t.string "type"
|
||||
t.string "fingerprint"
|
||||
t.boolean "public", default: false, null: false
|
||||
t.string "title", limit: 255
|
||||
t.string "type", limit: 255
|
||||
t.string "fingerprint", limit: 255
|
||||
t.boolean "public", default: false, null: false
|
||||
end
|
||||
|
||||
add_index "keys", ["created_at", "id"], name: "index_keys_on_created_at_and_id", using: :btree
|
||||
|
@ -424,7 +424,7 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
create_table "label_links", force: :cascade do |t|
|
||||
t.integer "label_id"
|
||||
t.integer "target_id"
|
||||
t.string "target_type"
|
||||
t.string "target_type", limit: 255
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
@ -433,22 +433,22 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "label_links", ["target_id", "target_type"], name: "index_label_links_on_target_id_and_target_type", using: :btree
|
||||
|
||||
create_table "labels", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.string "color"
|
||||
t.string "title", limit: 255
|
||||
t.string "color", limit: 255
|
||||
t.integer "project_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "template", default: false
|
||||
t.boolean "template", default: false
|
||||
end
|
||||
|
||||
add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree
|
||||
|
||||
create_table "lfs_objects", force: :cascade do |t|
|
||||
t.string "oid", null: false
|
||||
t.integer "size", null: false
|
||||
t.string "oid", limit: 255, null: false
|
||||
t.integer "size", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "file"
|
||||
t.string "file", limit: 255
|
||||
end
|
||||
|
||||
add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree
|
||||
|
@ -463,17 +463,17 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "lfs_objects_projects", ["project_id"], name: "index_lfs_objects_projects_on_project_id", using: :btree
|
||||
|
||||
create_table "members", force: :cascade do |t|
|
||||
t.integer "access_level", null: false
|
||||
t.integer "source_id", null: false
|
||||
t.string "source_type", null: false
|
||||
t.integer "access_level", null: false
|
||||
t.integer "source_id", null: false
|
||||
t.string "source_type", limit: 255, null: false
|
||||
t.integer "user_id"
|
||||
t.integer "notification_level", null: false
|
||||
t.string "type"
|
||||
t.integer "notification_level", null: false
|
||||
t.string "type", limit: 255
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "created_by_id"
|
||||
t.string "invite_email"
|
||||
t.string "invite_token"
|
||||
t.string "invite_email", limit: 255
|
||||
t.string "invite_token", limit: 255
|
||||
t.datetime "invite_accepted_at"
|
||||
end
|
||||
|
||||
|
@ -485,10 +485,10 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree
|
||||
|
||||
create_table "merge_request_diffs", force: :cascade do |t|
|
||||
t.string "state"
|
||||
t.string "state", limit: 255
|
||||
t.text "st_commits"
|
||||
t.text "st_diffs"
|
||||
t.integer "merge_request_id", null: false
|
||||
t.integer "merge_request_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
@ -496,26 +496,26 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "merge_request_diffs", ["merge_request_id"], name: "index_merge_request_diffs_on_merge_request_id", unique: true, using: :btree
|
||||
|
||||
create_table "merge_requests", force: :cascade do |t|
|
||||
t.string "target_branch", null: false
|
||||
t.string "source_branch", null: false
|
||||
t.integer "source_project_id", null: false
|
||||
t.string "target_branch", limit: 255, null: false
|
||||
t.string "source_branch", limit: 255, null: false
|
||||
t.integer "source_project_id", null: false
|
||||
t.integer "author_id"
|
||||
t.integer "assignee_id"
|
||||
t.string "title"
|
||||
t.string "title", limit: 255
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "milestone_id"
|
||||
t.string "state"
|
||||
t.string "merge_status"
|
||||
t.integer "target_project_id", null: false
|
||||
t.string "state", limit: 255
|
||||
t.string "merge_status", limit: 255
|
||||
t.integer "target_project_id", null: false
|
||||
t.integer "iid"
|
||||
t.text "description"
|
||||
t.integer "position", default: 0
|
||||
t.integer "position", default: 0
|
||||
t.datetime "locked_at"
|
||||
t.integer "updated_by_id"
|
||||
t.string "merge_error"
|
||||
t.string "merge_error", limit: 255
|
||||
t.text "merge_params"
|
||||
t.boolean "merge_when_build_succeeds", default: false, null: false
|
||||
t.boolean "merge_when_build_succeeds", default: false, null: false
|
||||
t.integer "merge_user_id"
|
||||
end
|
||||
|
||||
|
@ -531,13 +531,13 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "merge_requests", ["title"], name: "index_merge_requests_on_title", using: :btree
|
||||
|
||||
create_table "milestones", force: :cascade do |t|
|
||||
t.string "title", null: false
|
||||
t.integer "project_id", null: false
|
||||
t.string "title", limit: 255, null: false
|
||||
t.integer "project_id", null: false
|
||||
t.text "description"
|
||||
t.date "due_date"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "state"
|
||||
t.string "state", limit: 255
|
||||
t.integer "iid"
|
||||
end
|
||||
|
||||
|
@ -547,39 +547,37 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree
|
||||
|
||||
create_table "namespaces", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.string "path", null: false
|
||||
t.string "name", limit: 255, null: false
|
||||
t.string "path", limit: 255, null: false
|
||||
t.integer "owner_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "type"
|
||||
t.string "description", default: "", null: false
|
||||
t.string "avatar"
|
||||
t.boolean "public", default: false
|
||||
t.string "type", limit: 255
|
||||
t.string "description", limit: 255, default: "", null: false
|
||||
t.string "avatar", limit: 255
|
||||
end
|
||||
|
||||
add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree
|
||||
add_index "namespaces", ["name"], name: "index_namespaces_on_name", unique: true, using: :btree
|
||||
add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree
|
||||
add_index "namespaces", ["path"], name: "index_namespaces_on_path", unique: true, using: :btree
|
||||
add_index "namespaces", ["public"], name: "index_namespaces_on_public", using: :btree
|
||||
add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree
|
||||
|
||||
create_table "notes", force: :cascade do |t|
|
||||
t.text "note"
|
||||
t.string "noteable_type"
|
||||
t.string "noteable_type", limit: 255
|
||||
t.integer "author_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "project_id"
|
||||
t.string "attachment"
|
||||
t.string "line_code"
|
||||
t.string "commit_id"
|
||||
t.string "attachment", limit: 255
|
||||
t.string "line_code", limit: 255
|
||||
t.string "commit_id", limit: 255
|
||||
t.integer "noteable_id"
|
||||
t.boolean "system", default: false, null: false
|
||||
t.boolean "system", default: false, null: false
|
||||
t.text "st_diff"
|
||||
t.integer "updated_by_id"
|
||||
t.boolean "is_award", default: false, null: false
|
||||
t.boolean "is_award", default: false, null: false
|
||||
end
|
||||
|
||||
add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree
|
||||
|
@ -595,14 +593,14 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree
|
||||
|
||||
create_table "oauth_access_grants", force: :cascade do |t|
|
||||
t.integer "resource_owner_id", null: false
|
||||
t.integer "application_id", null: false
|
||||
t.string "token", null: false
|
||||
t.integer "expires_in", null: false
|
||||
t.text "redirect_uri", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.integer "resource_owner_id", null: false
|
||||
t.integer "application_id", null: false
|
||||
t.string "token", limit: 255, null: false
|
||||
t.integer "expires_in", null: false
|
||||
t.text "redirect_uri", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "revoked_at"
|
||||
t.string "scopes"
|
||||
t.string "scopes", limit: 255
|
||||
end
|
||||
|
||||
add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree
|
||||
|
@ -610,12 +608,12 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
create_table "oauth_access_tokens", force: :cascade do |t|
|
||||
t.integer "resource_owner_id"
|
||||
t.integer "application_id"
|
||||
t.string "token", null: false
|
||||
t.string "refresh_token"
|
||||
t.string "token", limit: 255, null: false
|
||||
t.string "refresh_token", limit: 255
|
||||
t.integer "expires_in"
|
||||
t.datetime "revoked_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.string "scopes"
|
||||
t.datetime "created_at", null: false
|
||||
t.string "scopes", limit: 255
|
||||
end
|
||||
|
||||
add_index "oauth_access_tokens", ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true, using: :btree
|
||||
|
@ -623,15 +621,15 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree
|
||||
|
||||
create_table "oauth_applications", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.string "uid", null: false
|
||||
t.string "secret", null: false
|
||||
t.text "redirect_uri", null: false
|
||||
t.string "scopes", default: "", null: false
|
||||
t.string "name", limit: 255, null: false
|
||||
t.string "uid", limit: 255, null: false
|
||||
t.string "secret", limit: 255, null: false
|
||||
t.text "redirect_uri", null: false
|
||||
t.string "scopes", limit: 255, default: "", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "owner_id"
|
||||
t.string "owner_type"
|
||||
t.string "owner_type", limit: 255
|
||||
end
|
||||
|
||||
add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree
|
||||
|
@ -643,39 +641,39 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
end
|
||||
|
||||
create_table "projects", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "path"
|
||||
t.string "name", limit: 255
|
||||
t.string "path", limit: 255
|
||||
t.text "description"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "creator_id"
|
||||
t.boolean "issues_enabled", default: true, null: false
|
||||
t.boolean "wall_enabled", default: true, null: false
|
||||
t.boolean "merge_requests_enabled", default: true, null: false
|
||||
t.boolean "wiki_enabled", default: true, null: false
|
||||
t.boolean "issues_enabled", default: true, null: false
|
||||
t.boolean "wall_enabled", default: true, null: false
|
||||
t.boolean "merge_requests_enabled", default: true, null: false
|
||||
t.boolean "wiki_enabled", default: true, null: false
|
||||
t.integer "namespace_id"
|
||||
t.string "issues_tracker", default: "gitlab", null: false
|
||||
t.string "issues_tracker_id"
|
||||
t.boolean "snippets_enabled", default: true, null: false
|
||||
t.string "issues_tracker", limit: 255, default: "gitlab", null: false
|
||||
t.string "issues_tracker_id", limit: 255
|
||||
t.boolean "snippets_enabled", default: true, null: false
|
||||
t.datetime "last_activity_at"
|
||||
t.string "import_url"
|
||||
t.integer "visibility_level", default: 0, null: false
|
||||
t.boolean "archived", default: false, null: false
|
||||
t.string "avatar"
|
||||
t.string "import_status"
|
||||
t.float "repository_size", default: 0.0
|
||||
t.integer "star_count", default: 0, null: false
|
||||
t.string "import_type"
|
||||
t.string "import_source"
|
||||
t.integer "commit_count", default: 0
|
||||
t.string "import_url", limit: 255
|
||||
t.integer "visibility_level", default: 0, null: false
|
||||
t.boolean "archived", default: false, null: false
|
||||
t.string "avatar", limit: 255
|
||||
t.string "import_status", limit: 255
|
||||
t.float "repository_size", default: 0.0
|
||||
t.integer "star_count", default: 0, null: false
|
||||
t.string "import_type", limit: 255
|
||||
t.string "import_source", limit: 255
|
||||
t.integer "commit_count", default: 0
|
||||
t.text "import_error"
|
||||
t.integer "ci_id"
|
||||
t.boolean "builds_enabled", default: true, null: false
|
||||
t.boolean "shared_runners_enabled", default: true, null: false
|
||||
t.boolean "builds_enabled", default: true, null: false
|
||||
t.boolean "shared_runners_enabled", default: true, null: false
|
||||
t.string "runners_token"
|
||||
t.string "build_coverage_regex"
|
||||
t.boolean "build_allow_git_fetch", default: true, null: false
|
||||
t.integer "build_timeout", default: 3600, null: false
|
||||
t.boolean "build_allow_git_fetch", default: true, null: false
|
||||
t.integer "build_timeout", default: 3600, null: false
|
||||
end
|
||||
|
||||
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
|
||||
|
@ -691,17 +689,17 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "projects", ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree
|
||||
|
||||
create_table "protected_branches", force: :cascade do |t|
|
||||
t.integer "project_id", null: false
|
||||
t.string "name", null: false
|
||||
t.integer "project_id", null: false
|
||||
t.string "name", limit: 255, null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "developers_can_push", default: false, null: false
|
||||
t.boolean "developers_can_push", default: false, null: false
|
||||
end
|
||||
|
||||
add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
|
||||
|
||||
create_table "releases", force: :cascade do |t|
|
||||
t.string "tag"
|
||||
t.string "tag", limit: 255
|
||||
t.text "description"
|
||||
t.integer "project_id"
|
||||
t.datetime "created_at"
|
||||
|
@ -714,30 +712,30 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
create_table "sent_notifications", force: :cascade do |t|
|
||||
t.integer "project_id"
|
||||
t.integer "noteable_id"
|
||||
t.string "noteable_type"
|
||||
t.string "noteable_type", limit: 255
|
||||
t.integer "recipient_id"
|
||||
t.string "commit_id"
|
||||
t.string "reply_key", null: false
|
||||
t.string "line_code"
|
||||
t.string "commit_id", limit: 255
|
||||
t.string "reply_key", limit: 255, null: false
|
||||
t.string "line_code", limit: 255
|
||||
end
|
||||
|
||||
add_index "sent_notifications", ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree
|
||||
|
||||
create_table "services", force: :cascade do |t|
|
||||
t.string "type"
|
||||
t.string "title"
|
||||
t.string "type", limit: 255
|
||||
t.string "title", limit: 255
|
||||
t.integer "project_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "active", default: false, null: false
|
||||
t.boolean "active", default: false, null: false
|
||||
t.text "properties"
|
||||
t.boolean "template", default: false
|
||||
t.boolean "push_events", default: true
|
||||
t.boolean "issues_events", default: true
|
||||
t.boolean "merge_requests_events", default: true
|
||||
t.boolean "tag_push_events", default: true
|
||||
t.boolean "note_events", default: true, null: false
|
||||
t.boolean "build_events", default: false, null: false
|
||||
t.boolean "template", default: false
|
||||
t.boolean "push_events", default: true
|
||||
t.boolean "issues_events", default: true
|
||||
t.boolean "merge_requests_events", default: true
|
||||
t.boolean "tag_push_events", default: true
|
||||
t.boolean "note_events", default: true, null: false
|
||||
t.boolean "build_events", default: false, null: false
|
||||
end
|
||||
|
||||
add_index "services", ["created_at", "id"], name: "index_services_on_created_at_and_id", using: :btree
|
||||
|
@ -745,16 +743,16 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "services", ["template"], name: "index_services_on_template", using: :btree
|
||||
|
||||
create_table "snippets", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.string "title", limit: 255
|
||||
t.text "content"
|
||||
t.integer "author_id", null: false
|
||||
t.integer "author_id", null: false
|
||||
t.integer "project_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "file_name"
|
||||
t.string "file_name", limit: 255
|
||||
t.datetime "expires_at"
|
||||
t.string "type"
|
||||
t.integer "visibility_level", default: 0, null: false
|
||||
t.string "type", limit: 255
|
||||
t.integer "visibility_level", default: 0, null: false
|
||||
end
|
||||
|
||||
add_index "snippets", ["author_id"], name: "index_snippets_on_author_id", using: :btree
|
||||
|
@ -767,7 +765,7 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
create_table "subscriptions", force: :cascade do |t|
|
||||
t.integer "user_id"
|
||||
t.integer "subscribable_id"
|
||||
t.string "subscribable_type"
|
||||
t.string "subscribable_type", limit: 255
|
||||
t.boolean "subscribed"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
|
@ -778,10 +776,10 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
create_table "taggings", force: :cascade do |t|
|
||||
t.integer "tag_id"
|
||||
t.integer "taggable_id"
|
||||
t.string "taggable_type"
|
||||
t.string "taggable_type", limit: 255
|
||||
t.integer "tagger_id"
|
||||
t.string "tagger_type"
|
||||
t.string "context"
|
||||
t.string "tagger_type", limit: 255
|
||||
t.string "context", limit: 255
|
||||
t.datetime "created_at"
|
||||
end
|
||||
|
||||
|
@ -789,67 +787,67 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree
|
||||
|
||||
create_table "tags", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "taggings_count", default: 0
|
||||
t.string "name", limit: 255
|
||||
t.integer "taggings_count", default: 0
|
||||
end
|
||||
|
||||
add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
|
||||
|
||||
create_table "users", force: :cascade do |t|
|
||||
t.string "email", default: "", null: false
|
||||
t.string "encrypted_password", default: "", null: false
|
||||
t.string "reset_password_token"
|
||||
t.string "email", limit: 255, default: "", null: false
|
||||
t.string "encrypted_password", limit: 255, default: "", null: false
|
||||
t.string "reset_password_token", limit: 255
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.integer "sign_in_count", default: 0
|
||||
t.integer "sign_in_count", default: 0
|
||||
t.datetime "current_sign_in_at"
|
||||
t.datetime "last_sign_in_at"
|
||||
t.string "current_sign_in_ip"
|
||||
t.string "last_sign_in_ip"
|
||||
t.string "current_sign_in_ip", limit: 255
|
||||
t.string "last_sign_in_ip", limit: 255
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "name"
|
||||
t.boolean "admin", default: false, null: false
|
||||
t.integer "projects_limit", default: 10
|
||||
t.string "skype", default: "", null: false
|
||||
t.string "linkedin", default: "", null: false
|
||||
t.string "twitter", default: "", null: false
|
||||
t.string "authentication_token"
|
||||
t.integer "theme_id", default: 1, null: false
|
||||
t.string "bio"
|
||||
t.integer "failed_attempts", default: 0
|
||||
t.string "name", limit: 255
|
||||
t.boolean "admin", default: false, null: false
|
||||
t.integer "projects_limit", default: 10
|
||||
t.string "skype", limit: 255, default: "", null: false
|
||||
t.string "linkedin", limit: 255, default: "", null: false
|
||||
t.string "twitter", limit: 255, default: "", null: false
|
||||
t.string "authentication_token", limit: 255
|
||||
t.integer "theme_id", default: 1, null: false
|
||||
t.string "bio", limit: 255
|
||||
t.integer "failed_attempts", default: 0
|
||||
t.datetime "locked_at"
|
||||
t.string "username"
|
||||
t.boolean "can_create_group", default: true, null: false
|
||||
t.boolean "can_create_team", default: true, null: false
|
||||
t.string "state"
|
||||
t.integer "color_scheme_id", default: 1, null: false
|
||||
t.integer "notification_level", default: 1, null: false
|
||||
t.string "username", limit: 255
|
||||
t.boolean "can_create_group", default: true, null: false
|
||||
t.boolean "can_create_team", default: true, null: false
|
||||
t.string "state", limit: 255
|
||||
t.integer "color_scheme_id", default: 1, null: false
|
||||
t.integer "notification_level", default: 1, null: false
|
||||
t.datetime "password_expires_at"
|
||||
t.integer "created_by_id"
|
||||
t.datetime "last_credential_check_at"
|
||||
t.string "avatar"
|
||||
t.string "confirmation_token"
|
||||
t.string "avatar", limit: 255
|
||||
t.string "confirmation_token", limit: 255
|
||||
t.datetime "confirmed_at"
|
||||
t.datetime "confirmation_sent_at"
|
||||
t.string "unconfirmed_email"
|
||||
t.boolean "hide_no_ssh_key", default: false
|
||||
t.string "website_url", default: "", null: false
|
||||
t.string "notification_email"
|
||||
t.boolean "hide_no_password", default: false
|
||||
t.boolean "password_automatically_set", default: false
|
||||
t.string "location"
|
||||
t.string "encrypted_otp_secret"
|
||||
t.string "encrypted_otp_secret_iv"
|
||||
t.string "encrypted_otp_secret_salt"
|
||||
t.boolean "otp_required_for_login", default: false, null: false
|
||||
t.string "unconfirmed_email", limit: 255
|
||||
t.boolean "hide_no_ssh_key", default: false
|
||||
t.string "website_url", limit: 255, default: "", null: false
|
||||
t.string "notification_email", limit: 255
|
||||
t.boolean "hide_no_password", default: false
|
||||
t.boolean "password_automatically_set", default: false
|
||||
t.string "location", limit: 255
|
||||
t.string "encrypted_otp_secret", limit: 255
|
||||
t.string "encrypted_otp_secret_iv", limit: 255
|
||||
t.string "encrypted_otp_secret_salt", limit: 255
|
||||
t.boolean "otp_required_for_login", default: false, null: false
|
||||
t.text "otp_backup_codes"
|
||||
t.string "public_email", default: "", null: false
|
||||
t.integer "dashboard", default: 0
|
||||
t.integer "project_view", default: 0
|
||||
t.string "public_email", limit: 255, default: "", null: false
|
||||
t.integer "dashboard", default: 0
|
||||
t.integer "project_view", default: 0
|
||||
t.integer "consumed_timestep"
|
||||
t.integer "layout", default: 0
|
||||
t.boolean "hide_project_limit", default: false
|
||||
t.integer "layout", default: 0
|
||||
t.boolean "hide_project_limit", default: false
|
||||
t.string "unlock_token"
|
||||
t.datetime "otp_grace_period_started_at"
|
||||
end
|
||||
|
@ -876,19 +874,19 @@ ActiveRecord::Schema.define(version: 20151229112614) do
|
|||
add_index "users_star_projects", ["user_id"], name: "index_users_star_projects_on_user_id", using: :btree
|
||||
|
||||
create_table "web_hooks", force: :cascade do |t|
|
||||
t.string "url"
|
||||
t.string "url", limit: 255
|
||||
t.integer "project_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "type", default: "ProjectHook"
|
||||
t.string "type", limit: 255, default: "ProjectHook"
|
||||
t.integer "service_id"
|
||||
t.boolean "push_events", default: true, null: false
|
||||
t.boolean "issues_events", default: false, null: false
|
||||
t.boolean "merge_requests_events", default: false, null: false
|
||||
t.boolean "tag_push_events", default: false
|
||||
t.boolean "note_events", default: false, null: false
|
||||
t.boolean "enable_ssl_verification", default: true
|
||||
t.boolean "build_events", default: false, null: false
|
||||
t.boolean "push_events", default: true, null: false
|
||||
t.boolean "issues_events", default: false, null: false
|
||||
t.boolean "merge_requests_events", default: false, null: false
|
||||
t.boolean "tag_push_events", default: false
|
||||
t.boolean "note_events", default: false, null: false
|
||||
t.boolean "enable_ssl_verification", default: true
|
||||
t.boolean "build_events", default: false, null: false
|
||||
end
|
||||
|
||||
add_index "web_hooks", ["created_at", "id"], name: "index_web_hooks_on_created_at_and_id", using: :btree
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
- [GitLab Basics](gitlab-basics/README.md) Find step by step how to start working on your commandline and on GitLab.
|
||||
- [Importing to GitLab](workflow/importing/README.md).
|
||||
- [Markdown](markdown/markdown.md) GitLab's advanced formatting system.
|
||||
- [Migrating from SVN](migration/README.md) Convert a SVN repository to Git and GitLab
|
||||
- [Migrating from SVN](workflow/importing/migrating_from_svn.md) Convert a SVN repository to Git and GitLab
|
||||
- [Permissions](permissions/permissions.md) Learn what each role in a project (guest/reporter/developer/master/owner) can do.
|
||||
- [Profile Settings](profile/README.md)
|
||||
- [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat.
|
||||
|
@ -56,7 +56,7 @@
|
|||
- [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages.
|
||||
- [Libravatar](customization/libravatar.md) Use Libravatar for user avatars.
|
||||
- [Log system](logs/logs.md) Log system.
|
||||
- [Environmental Variables](administration/environmental_variables.md) to configure GitLab.
|
||||
- [Environment Variables](administration/environment_variables.md) to configure GitLab.
|
||||
- [Operations](operations/README.md) Keeping GitLab up and running
|
||||
- [Raketasks](raketasks/README.md) Backups, maintenance, automatic web hook setup and the importing of projects.
|
||||
- [Security](security/README.md) Learn what you can do to further secure your GitLab instance.
|
||||
|
|
|
@ -9,11 +9,14 @@ But if you prefer to use environment variables we allow that too.
|
|||
## Supported environment variables
|
||||
|
||||
Variable | Type | Explanation
|
||||
--- | --- | ---
|
||||
-------- | ---- | -----------
|
||||
GITLAB_ROOT_PASSWORD | string | sets the password for the `root` user on installation
|
||||
GITLAB_HOST | url | hostname of the GitLab server includes http or https
|
||||
RAILS_ENV | production/development/staging/test | Rails environment
|
||||
RAILS_ENV | production / development / staging / test | Rails environment
|
||||
DATABASE_URL | url | For example: postgresql://localhost/blog_development?pool=5
|
||||
GITLAB_EMAIL_FROM | email | Email address used in the "From" field in mails sent by GitLab
|
||||
GITLAB_EMAIL_DISPLAY_NAME | string | Name used in the "From" field in mails sent by GitLab
|
||||
GITLAB_EMAIL_REPLY_TO | email | Email address used in the "Reply-To" field in mails sent by GitLab
|
||||
|
||||
## Complete database variables
|
||||
|
||||
|
@ -39,7 +42,12 @@ GITLAB_DATABASE_PASSWORD |
|
|||
GITLAB_DATABASE_HOST | localhost
|
||||
GITLAB_DATABASE_PORT | 5432
|
||||
|
||||
## Other variables
|
||||
## Adding more variables
|
||||
|
||||
We welcome merge requests to make more settings configurable via variables.
|
||||
Please stick to the naming scheme "GITLAB_#{name 1_settings.rb in upper case}".
|
||||
|
||||
## Omnibus configuration
|
||||
|
||||
It's possible to preconfigure the GitLab image by adding the environment variable: `GITLAB_OMNIBUS_CONFIG` to docker run command.
|
||||
For more information see the ['preconfigure-docker-container' section in the Omnibus documentation](http://doc.gitlab.com/omnibus/docker/#preconfigure-docker-container).
|
|
@ -153,6 +153,49 @@ with the name of your bucket:
|
|||
}
|
||||
```
|
||||
|
||||
### Uploading to locally mounted shares
|
||||
|
||||
You may also send backups to a mounted share (`NFS` / `CIFS` / `SMB` / etc.) by
|
||||
using the [`Local`](https://github.com/fog/fog-local#usage) storage provider.
|
||||
The directory pointed to by the `local_root` key **must** be owned by the `git`
|
||||
user **when mounted** (mounting with the `uid=` of the `git` user for `CIFS` and
|
||||
`SMB`) or the user that you are executing the backup tasks under (for omnibus
|
||||
packages, this is the `git` user).
|
||||
|
||||
The `backup_upload_remote_directory` **must** be set in addition to the
|
||||
`local_root` key. This is the sub directory inside the mounted directory that
|
||||
backups will be copied to, and will be created if it does not exist. If the
|
||||
directory that you want to copy the tarballs to is the root of your mounted
|
||||
directory, just use `.` instead.
|
||||
|
||||
For omnibus packages:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['backup_upload_connection'] = {
|
||||
:provider => 'Local',
|
||||
:local_root => '/mnt/backups'
|
||||
}
|
||||
|
||||
# The directory inside the mounted folder to copy backups to
|
||||
# Use '.' to store them in the root directory
|
||||
gitlab_rails['backup_upload_remote_directory'] = 'gitlab_backups'
|
||||
```
|
||||
|
||||
For installations from source:
|
||||
|
||||
```yaml
|
||||
backup:
|
||||
# snip
|
||||
upload:
|
||||
# Fog storage connection settings, see http://fog.io/storage/ .
|
||||
connection:
|
||||
provider: Local
|
||||
local_root: '/mnt/backups'
|
||||
# The directory inside the mounted folder to copy backups to
|
||||
# Use '.' to store them in the root directory
|
||||
remote_directory: 'gitlab_backups'
|
||||
```
|
||||
|
||||
## Backup archive permissions
|
||||
|
||||
The backup archives created by GitLab (123456_gitlab_backup.tar) will have owner/group git:git and 0600 permissions by default.
|
||||
|
|
|
@ -9,7 +9,7 @@ already has one by running the following command:
|
|||
cat ~/.ssh/id_rsa.pub
|
||||
```
|
||||
|
||||
If you see a long string starting with `ssh-rsa` or `ssh-dsa`, you can skip the `ssh-keygen` step.
|
||||
If you see a long string starting with `ssh-rsa`, you can skip the `ssh-keygen` step.
|
||||
|
||||
Note: It is a best practice to use a password for an SSH key, but it is not
|
||||
required and you can skip creating a password by pressing enter. Note that
|
||||
|
@ -20,8 +20,9 @@ To generate a new SSH key, use the following command:
|
|||
ssh-keygen -t rsa -C "$your_email"
|
||||
```
|
||||
This command will prompt you for a location and filename to store the key
|
||||
pair and for a password. When prompted for the location and filename, you
|
||||
can press enter to use the default.
|
||||
pair and for a password. When prompted for the location and filename, just
|
||||
press enter to use the default. If you use a different name, the key will not
|
||||
be used automatically.
|
||||
|
||||
Use the command below to show your public key:
|
||||
```bash
|
||||
|
@ -29,10 +30,10 @@ cat ~/.ssh/id_rsa.pub
|
|||
```
|
||||
|
||||
Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your
|
||||
user profile. Please copy the complete key starting with `ssh-` and ending
|
||||
user profile. Please copy the complete key starting with `ssh-rsa` and ending
|
||||
with your username and host.
|
||||
|
||||
To copy your public key to the clipboard, use code below. Depending on your
|
||||
To copy your public key to the clipboard, use the code below. Depending on your
|
||||
OS you'll need to use a different command:
|
||||
|
||||
**Windows:**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# System hooks
|
||||
|
||||
Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`.
|
||||
Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `project_rename`, `project_transfer`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`.
|
||||
|
||||
System hooks can be used, e.g. for logging or changing information in a LDAP server.
|
||||
|
||||
|
@ -17,6 +17,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:54Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "project_create",
|
||||
"name": "StoreCloud",
|
||||
"owner_email": "johnsmith@gmail.com",
|
||||
|
@ -33,6 +34,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:58Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "project_destroy",
|
||||
"name": "Underscore",
|
||||
"owner_email": "johnsmith@gmail.com",
|
||||
|
@ -44,11 +46,48 @@ X-Gitlab-Event: System Hook
|
|||
}
|
||||
```
|
||||
|
||||
**Project renamed:**
|
||||
|
||||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:58Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "project_rename",
|
||||
"name": "Underscore",
|
||||
"path": "underscore",
|
||||
"path_with_namespace": "jsmith/underscore",
|
||||
"project_id": 73,
|
||||
"owner_name": "John Smith",
|
||||
"owner_email": "johnsmith@gmail.com",
|
||||
"project_visibility": "internal",
|
||||
"old_path_with_namespace": "jsmith/overscore",
|
||||
}
|
||||
```
|
||||
|
||||
**Project transferred:**
|
||||
|
||||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:58Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "project_transfer",
|
||||
"name": "Underscore",
|
||||
"path": "underscore",
|
||||
"path_with_namespace": "scores/underscore",
|
||||
"project_id": 73,
|
||||
"owner_name": "John Smith",
|
||||
"owner_email": "johnsmith@gmail.com",
|
||||
"project_visibility": "internal",
|
||||
"old_path_with_namespace": "jsmith/overscore",
|
||||
}
|
||||
```
|
||||
|
||||
**New Team Member:**
|
||||
|
||||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:56Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "user_add_to_team",
|
||||
"project_access": "Master",
|
||||
"project_id": 74,
|
||||
|
@ -67,6 +106,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:56Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "user_remove_from_team",
|
||||
"project_access": "Master",
|
||||
"project_id": 74,
|
||||
|
@ -85,6 +125,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:44:07Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"email": "js@gitlabhq.com",
|
||||
"event_name": "user_create",
|
||||
"name": "John Smith",
|
||||
|
@ -97,6 +138,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:44:07Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"email": "js@gitlabhq.com",
|
||||
"event_name": "user_destroy",
|
||||
"name": "John Smith",
|
||||
|
@ -110,6 +152,7 @@ X-Gitlab-Event: System Hook
|
|||
{
|
||||
"event_name": "key_create",
|
||||
"created_at": "2014-08-18 18:45:16 UTC",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"username": "root",
|
||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC58FwqHUbebw2SdT7SP4FxZ0w+lAO/erhy2ylhlcW/tZ3GY3mBu9VeeiSGoGz8hCx80Zrz+aQv28xfFfKlC8XQFpCWwsnWnQqO2Lv9bS8V1fIHgMxOHIt5Vs+9CAWGCCvUOAurjsUDoE2ALIXLDMKnJxcxD13XjWdK54j6ZXDB4syLF0C2PnAQSVY9X7MfCYwtuFmhQhKaBussAXpaVMRHltie3UYSBUUuZaB3J4cg/7TxlmxcNd+ppPRIpSZAB0NI6aOnqoBCpimscO/VpQRJMVLr3XiSYeT6HBiDXWHnIVPfQc03OGcaFqOit6p8lYKMaP/iUQLm+pgpZqrXZ9vB john@localhost",
|
||||
"id": 4
|
||||
|
@ -122,6 +165,7 @@ X-Gitlab-Event: System Hook
|
|||
{
|
||||
"event_name": "key_destroy",
|
||||
"created_at": "2014-08-18 18:45:16 UTC",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"username": "root",
|
||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC58FwqHUbebw2SdT7SP4FxZ0w+lAO/erhy2ylhlcW/tZ3GY3mBu9VeeiSGoGz8hCx80Zrz+aQv28xfFfKlC8XQFpCWwsnWnQqO2Lv9bS8V1fIHgMxOHIt5Vs+9CAWGCCvUOAurjsUDoE2ALIXLDMKnJxcxD13XjWdK54j6ZXDB4syLF0C2PnAQSVY9X7MfCYwtuFmhQhKaBussAXpaVMRHltie3UYSBUUuZaB3J4cg/7TxlmxcNd+ppPRIpSZAB0NI6aOnqoBCpimscO/VpQRJMVLr3XiSYeT6HBiDXWHnIVPfQc03OGcaFqOit6p8lYKMaP/iUQLm+pgpZqrXZ9vB john@localhost",
|
||||
"id": 4
|
||||
|
@ -133,6 +177,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:54Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "group_create",
|
||||
"name": "StoreCloud",
|
||||
"owner_email": "johnsmith@gmail.com",
|
||||
|
@ -147,6 +192,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:54Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "group_destroy",
|
||||
"name": "StoreCloud",
|
||||
"owner_email": "johnsmith@gmail.com",
|
||||
|
@ -161,6 +207,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:56Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "user_add_to_group",
|
||||
"group_access": "Master",
|
||||
"group_id": 78,
|
||||
|
@ -176,6 +223,7 @@ X-Gitlab-Event: System Hook
|
|||
```json
|
||||
{
|
||||
"created_at": "2012-07-21T07:30:56Z",
|
||||
"updated_at": "2012-07-21T07:38:22Z",
|
||||
"event_name": "user_remove_from_group",
|
||||
"group_access": "Master",
|
||||
"group_id": 78,
|
||||
|
|
|
@ -105,15 +105,6 @@ Feature: Explore Groups
|
|||
When I visit the public groups area
|
||||
Then I should see group "TestGroup"
|
||||
|
||||
Scenario: I should not see group with internal project in public groups area
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
When I visit the public groups area
|
||||
Then I should not see group "TestGroup"
|
||||
|
||||
Scenario: I should not see group with private project in public groups area
|
||||
When I visit the public groups area
|
||||
Then I should not see group "TestGroup"
|
||||
|
||||
Scenario: I should see group with public project in public groups area as user
|
||||
Given group "TestGroup" has public project "Community"
|
||||
When I sign in as a user
|
||||
|
@ -125,9 +116,3 @@ Feature: Explore Groups
|
|||
When I sign in as a user
|
||||
And I visit the public groups area
|
||||
Then I should see group "TestGroup"
|
||||
|
||||
Scenario: I should not see group with private project in public groups area as user
|
||||
When I sign in as a user
|
||||
And I visit the public groups area
|
||||
Then I should not see group "TestGroup"
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
|
|||
page.within '.awards' do
|
||||
expect do
|
||||
page.find('.award.active').click
|
||||
sleep 0.1
|
||||
sleep 0.3
|
||||
end.to change{ page.all(".award").size }.from(3).to(2)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -59,15 +59,14 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
|
|||
end
|
||||
|
||||
step 'I click "author" dropdown' do
|
||||
first('.ajax-users-select').click
|
||||
first('#s2id_author_id').click
|
||||
end
|
||||
|
||||
step 'I see current user as the first user' do
|
||||
expect(page).to have_selector('.user-result', visible: true, count: 4)
|
||||
expect(page).to have_selector('.user-result', visible: true, count: 3)
|
||||
users = page.all('.user-name')
|
||||
expect(users[0].text).to eq 'Any Assignee'
|
||||
expect(users[1].text).to eq 'Unassigned'
|
||||
expect(users[2].text).to eq current_user.name
|
||||
expect(users[0].text).to eq 'Any Author'
|
||||
expect(users[1].text).to eq current_user.name
|
||||
end
|
||||
|
||||
step 'I submit new issue "500 error on profile"' do
|
||||
|
|
|
@ -3,7 +3,7 @@ module API
|
|||
class Projects < Grape::API
|
||||
before { authenticate! }
|
||||
|
||||
resource :projects do
|
||||
resource :projects, requirements: { id: /[^\/]+/ } do
|
||||
helpers do
|
||||
def map_public_to_visibility_level(attrs)
|
||||
publik = attrs.delete(:public)
|
||||
|
|
|
@ -47,7 +47,17 @@ module Banzai
|
|||
{ object_sym => LazyReference.new(object_class, node.attr(data_reference)) }
|
||||
end
|
||||
|
||||
delegate :object_class, :object_sym, :references_in, to: :class
|
||||
def object_class
|
||||
self.class.object_class
|
||||
end
|
||||
|
||||
def object_sym
|
||||
self.class.object_sym
|
||||
end
|
||||
|
||||
def references_in(*args, &block)
|
||||
self.class.references_in(*args, &block)
|
||||
end
|
||||
|
||||
def find_object(project, id)
|
||||
# Implement in child class
|
||||
|
|
|
@ -10,7 +10,7 @@ module Banzai
|
|||
#
|
||||
class RedactorFilter < HTML::Pipeline::Filter
|
||||
def call
|
||||
doc.css('a.gfm').each do |node|
|
||||
Querying.css(doc, 'a.gfm').each do |node|
|
||||
unless user_can_see_reference?(node)
|
||||
# The reference should be replaced by the original text,
|
||||
# which is not always the same as the rendered text.
|
||||
|
|
|
@ -124,7 +124,7 @@ module Banzai
|
|||
def replace_link_nodes_with_text(pattern)
|
||||
return doc if project.nil?
|
||||
|
||||
doc.search('a').each do |node|
|
||||
doc.xpath('descendant-or-self::a').each do |node|
|
||||
klass = node.attr('class')
|
||||
next if klass && klass.include?('gfm')
|
||||
|
||||
|
@ -162,7 +162,7 @@ module Banzai
|
|||
def replace_link_nodes_with_href(pattern)
|
||||
return doc if project.nil?
|
||||
|
||||
doc.search('a').each do |node|
|
||||
doc.xpath('descendant-or-self::a').each do |node|
|
||||
klass = node.attr('class')
|
||||
next if klass && klass.include?('gfm')
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ module Banzai
|
|||
end
|
||||
|
||||
def call
|
||||
doc.css('a.gfm').each do |node|
|
||||
Querying.css(doc, 'a.gfm').each do |node|
|
||||
gather_references(node)
|
||||
end
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ module Banzai
|
|||
parts = request_path.split('/')
|
||||
parts.pop if path_type(request_path) != 'tree'
|
||||
|
||||
while parts.length > 1 && path.start_with?('../')
|
||||
while path.start_with?('../')
|
||||
parts.pop
|
||||
path.sub!('../', '')
|
||||
end
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
module Banzai
|
||||
module Querying
|
||||
# Searches a Nokogiri document using a CSS query, optionally optimizing it
|
||||
# whenever possible.
|
||||
#
|
||||
# document - A document/element to search.
|
||||
# query - The CSS query to use.
|
||||
#
|
||||
# Returns a Nokogiri::XML::NodeSet.
|
||||
def self.css(document, query)
|
||||
# When using "a.foo" Nokogiri compiles this to "//a[...]" but
|
||||
# "descendant::a[...]" is quite a bit faster and achieves the same result.
|
||||
xpath = Nokogiri::CSS.xpath_for(query)[0].gsub(%r{^//}, 'descendant::')
|
||||
|
||||
document.xpath(xpath)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,5 @@
|
|||
module Banzai
|
||||
module Renderer
|
||||
CACHE_ENABLED = false
|
||||
|
||||
# Convert a Markdown String into an HTML-safe String of HTML
|
||||
#
|
||||
# Note that while the returned HTML will have been sanitized of dangerous
|
||||
|
@ -20,13 +18,22 @@ module Banzai
|
|||
cache_key = context.delete(:cache_key)
|
||||
cache_key = full_cache_key(cache_key, context[:pipeline])
|
||||
|
||||
if cache_key && CACHE_ENABLED
|
||||
Rails.cache.fetch(cache_key) do
|
||||
cacheless_render(text, context)
|
||||
cacheless = cacheless_render(text, context)
|
||||
|
||||
if cache_key && ENV["DEBUG_BANZAI_CACHE"]
|
||||
cached = Rails.cache.fetch(cache_key) { cacheless }
|
||||
|
||||
if cached != cacheless
|
||||
Rails.logger.warn "Banzai cache mismatch"
|
||||
Rails.logger.warn "Text: #{text.inspect}"
|
||||
Rails.logger.warn "Context: #{context.inspect}"
|
||||
Rails.logger.warn "Cache key: #{cache_key.inspect}"
|
||||
Rails.logger.warn "Cacheless: #{cacheless.inspect}"
|
||||
Rails.logger.warn "With cache: #{cached.inspect}"
|
||||
end
|
||||
else
|
||||
cacheless_render(text, context)
|
||||
end
|
||||
|
||||
cacheless
|
||||
end
|
||||
|
||||
def self.render_result(text, context = {})
|
||||
|
|
|
@ -45,11 +45,11 @@ module Gitlab
|
|||
end
|
||||
|
||||
def starting_year
|
||||
(Time.now - 1.year).strftime("%Y")
|
||||
1.year.ago.year
|
||||
end
|
||||
|
||||
def starting_month
|
||||
Date.today.strftime("%m").to_i
|
||||
Date.today.month
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -38,7 +38,9 @@ module Gitlab
|
|||
true
|
||||
end
|
||||
|
||||
use_db && ActiveRecord::Base.connection.active? && ActiveRecord::Base.connection.table_exists?('application_settings')
|
||||
use_db && ActiveRecord::Base.connection.active? &&
|
||||
!ActiveRecord::Migrator.needs_migration? &&
|
||||
ActiveRecord::Base.connection.table_exists?('application_settings')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,16 +6,21 @@ module Gitlab
|
|||
METRICS_ROOT = Rails.root.join('lib', 'gitlab', 'metrics').to_s
|
||||
PATH_REGEX = /^#{RAILS_ROOT}\/?/
|
||||
|
||||
def self.pool_size
|
||||
current_application_settings[:metrics_pool_size] || 16
|
||||
end
|
||||
|
||||
def self.timeout
|
||||
current_application_settings[:metrics_timeout] || 10
|
||||
def self.settings
|
||||
@settings ||= {
|
||||
enabled: current_application_settings[:metrics_enabled],
|
||||
pool_size: current_application_settings[:metrics_pool_size],
|
||||
timeout: current_application_settings[:metrics_timeout],
|
||||
method_call_threshold: current_application_settings[:metrics_method_call_threshold],
|
||||
host: current_application_settings[:metrics_host],
|
||||
username: current_application_settings[:metrics_username],
|
||||
password: current_application_settings[:metrics_password],
|
||||
port: current_application_settings[:metrics_port]
|
||||
}
|
||||
end
|
||||
|
||||
def self.enabled?
|
||||
current_application_settings[:metrics_enabled] || false
|
||||
settings[:enabled] || false
|
||||
end
|
||||
|
||||
def self.mri?
|
||||
|
@ -26,18 +31,13 @@ module Gitlab
|
|||
# This is memoized since this method is called for every instrumented
|
||||
# method. Loading data from an external cache on every method call slows
|
||||
# things down too much.
|
||||
@method_call_threshold ||=
|
||||
(current_application_settings[:metrics_method_call_threshold] || 10)
|
||||
@method_call_threshold ||= settings[:method_call_threshold]
|
||||
end
|
||||
|
||||
def self.pool
|
||||
@pool
|
||||
end
|
||||
|
||||
def self.hostname
|
||||
@hostname
|
||||
end
|
||||
|
||||
# Returns a relative path and line number based on the last application call
|
||||
# frame.
|
||||
def self.last_relative_application_frame
|
||||
|
@ -85,16 +85,14 @@ module Gitlab
|
|||
value.to_s.gsub('=', '\\=')
|
||||
end
|
||||
|
||||
@hostname = Socket.gethostname
|
||||
|
||||
# When enabled this should be set before being used as the usual pattern
|
||||
# "@foo ||= bar" is _not_ thread-safe.
|
||||
if enabled?
|
||||
@pool = ConnectionPool.new(size: pool_size, timeout: timeout) do
|
||||
host = current_application_settings[:metrics_host]
|
||||
user = current_application_settings[:metrics_username]
|
||||
pw = current_application_settings[:metrics_password]
|
||||
port = current_application_settings[:metrics_port]
|
||||
@pool = ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do
|
||||
host = settings[:host]
|
||||
user = settings[:username]
|
||||
pw = settings[:password]
|
||||
port = settings[:port]
|
||||
|
||||
InfluxDB::Client.
|
||||
new(udp: { host: host, port: port }, username: user, password: pw)
|
||||
|
|
|
@ -123,6 +123,8 @@ module Gitlab
|
|||
duration = (Time.now - start) * 1000.0
|
||||
|
||||
if duration >= Gitlab::Metrics.method_call_threshold
|
||||
trans.increment(:method_duration, duration)
|
||||
|
||||
trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES,
|
||||
{ duration: duration },
|
||||
method: #{label.inspect})
|
||||
|
|
|
@ -17,14 +17,8 @@ module Gitlab
|
|||
# Returns a Hash in a format that can be directly written to InfluxDB.
|
||||
def to_hash
|
||||
{
|
||||
series: @series,
|
||||
tags: @tags.merge(
|
||||
hostname: Metrics.hostname,
|
||||
ruby_engine: RUBY_ENGINE,
|
||||
ruby_version: RUBY_VERSION,
|
||||
gitlab_version: Gitlab::VERSION,
|
||||
process_type: Sidekiq.server? ? 'sidekiq' : 'rails'
|
||||
),
|
||||
series: @series,
|
||||
tags: @tags,
|
||||
values: @values,
|
||||
timestamp: @created_at.to_i * 1_000_000_000
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
module Gitlab
|
||||
module Metrics
|
||||
# Class for producing SQL queries with sensitive data stripped out.
|
||||
class ObfuscatedSQL
|
||||
REPLACEMENT = /
|
||||
\d+(\.\d+)? # integers, floats
|
||||
| '.+?' # single quoted strings
|
||||
| \/.+?(?<!\\)\/ # regexps (including escaped slashes)
|
||||
/x
|
||||
|
||||
MYSQL_REPLACEMENTS = /
|
||||
".+?" # double quoted strings
|
||||
/x
|
||||
|
||||
# Regex to replace consecutive placeholders with a single one indicating
|
||||
# the length. This can be useful when a "IN" statement uses thousands of
|
||||
# IDs (storing this would just be a waste of space).
|
||||
CONSECUTIVE = /(\?(\s*,\s*)?){2,}/
|
||||
|
||||
# sql - The raw SQL query as a String.
|
||||
def initialize(sql)
|
||||
@sql = sql
|
||||
end
|
||||
|
||||
# Returns a new, obfuscated SQL query.
|
||||
def to_s
|
||||
regex = REPLACEMENT
|
||||
|
||||
if Gitlab::Database.mysql?
|
||||
regex = Regexp.union(regex, MYSQL_REPLACEMENTS)
|
||||
end
|
||||
|
||||
sql = @sql.gsub(regex, '?').gsub(CONSECUTIVE) do |match|
|
||||
"#{match.count(',') + 1} values"
|
||||
end
|
||||
|
||||
# InfluxDB escapes double quotes upon output, so lets get rid of them
|
||||
# whenever we can.
|
||||
if Gitlab::Database.postgresql?
|
||||
sql = sql.delete('"')
|
||||
end
|
||||
|
||||
sql.tr("\n", ' ')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -50,12 +50,11 @@ module Gitlab
|
|||
end
|
||||
|
||||
def sample_memory_usage
|
||||
@metrics << Metric.new('memory_usage', value: System.memory_usage)
|
||||
add_metric('memory_usage', value: System.memory_usage)
|
||||
end
|
||||
|
||||
def sample_file_descriptors
|
||||
@metrics << Metric.
|
||||
new('file_descriptors', value: System.file_descriptor_count)
|
||||
add_metric('file_descriptors', value: System.file_descriptor_count)
|
||||
end
|
||||
|
||||
if Metrics.mri?
|
||||
|
@ -69,7 +68,7 @@ module Gitlab
|
|||
counts['Symbol'] = Symbol.all_symbols.length
|
||||
|
||||
counts.each do |name, count|
|
||||
@metrics << Metric.new('object_counts', { count: count }, type: name)
|
||||
add_metric('object_counts', { count: count }, type: name)
|
||||
end
|
||||
end
|
||||
else
|
||||
|
@ -91,7 +90,17 @@ module Gitlab
|
|||
|
||||
stats[:count] = stats[:minor_gc_count] + stats[:major_gc_count]
|
||||
|
||||
@metrics << Metric.new('gc_statistics', stats)
|
||||
add_metric('gc_statistics', stats)
|
||||
end
|
||||
|
||||
def add_metric(series, values, tags = {})
|
||||
prefix = sidekiq? ? 'sidekiq_' : 'rails_'
|
||||
|
||||
@metrics << Metric.new("#{prefix}#{series}", values, tags)
|
||||
end
|
||||
|
||||
def sidekiq?
|
||||
Sidekiq.server?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,6 +19,7 @@ module Gitlab
|
|||
values = values_for(event)
|
||||
tags = tags_for(event)
|
||||
|
||||
current_transaction.increment(:view_duration, event.duration)
|
||||
current_transaction.add_metric(SERIES, values, tags)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,44 +1,18 @@
|
|||
module Gitlab
|
||||
module Metrics
|
||||
module Subscribers
|
||||
# Class for tracking raw SQL queries.
|
||||
#
|
||||
# Queries are obfuscated before being logged to ensure no private data is
|
||||
# exposed via InfluxDB/Grafana.
|
||||
# Class for tracking the total query duration of a transaction.
|
||||
class ActiveRecord < ActiveSupport::Subscriber
|
||||
attach_to :active_record
|
||||
|
||||
SERIES = 'sql_queries'
|
||||
|
||||
def sql(event)
|
||||
return unless current_transaction
|
||||
|
||||
values = values_for(event)
|
||||
tags = tags_for(event)
|
||||
|
||||
current_transaction.add_metric(SERIES, values, tags)
|
||||
current_transaction.increment(:sql_duration, event.duration)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def values_for(event)
|
||||
{ duration: event.duration }
|
||||
end
|
||||
|
||||
def tags_for(event)
|
||||
sql = ObfuscatedSQL.new(event.payload[:sql]).to_s
|
||||
tags = { sql: sql }
|
||||
|
||||
file, line = Metrics.last_relative_application_frame
|
||||
|
||||
if file and line
|
||||
tags[:file] = file
|
||||
tags[:line] = line
|
||||
end
|
||||
|
||||
tags
|
||||
end
|
||||
|
||||
def current_transaction
|
||||
Transaction.current
|
||||
end
|
||||
|
|
|
@ -4,15 +4,12 @@ module Gitlab
|
|||
class Transaction
|
||||
THREAD_KEY = :_gitlab_metrics_transaction
|
||||
|
||||
SERIES = 'transactions'
|
||||
|
||||
attr_reader :uuid, :tags
|
||||
|
||||
def self.current
|
||||
Thread.current[THREAD_KEY]
|
||||
end
|
||||
|
||||
# name - The name of this transaction as a String.
|
||||
def initialize
|
||||
@metrics = []
|
||||
@uuid = SecureRandom.uuid
|
||||
|
@ -20,7 +17,8 @@ module Gitlab
|
|||
@started_at = nil
|
||||
@finished_at = nil
|
||||
|
||||
@tags = {}
|
||||
@values = Hash.new(0)
|
||||
@tags = {}
|
||||
end
|
||||
|
||||
def duration
|
||||
|
@ -40,9 +38,14 @@ module Gitlab
|
|||
end
|
||||
|
||||
def add_metric(series, values, tags = {})
|
||||
tags = tags.merge(transaction_id: @uuid)
|
||||
tags = tags.merge(transaction_id: @uuid)
|
||||
prefix = sidekiq? ? 'sidekiq_' : 'rails_'
|
||||
|
||||
@metrics << Metric.new(series, values, tags)
|
||||
@metrics << Metric.new("#{prefix}#{series}", values, tags)
|
||||
end
|
||||
|
||||
def increment(name, value)
|
||||
@values[name] += value
|
||||
end
|
||||
|
||||
def add_tag(key, value)
|
||||
|
@ -55,12 +58,22 @@ module Gitlab
|
|||
end
|
||||
|
||||
def track_self
|
||||
add_metric(SERIES, { duration: duration }, @tags)
|
||||
values = { duration: duration }
|
||||
|
||||
@values.each do |name, value|
|
||||
values[name] = value
|
||||
end
|
||||
|
||||
add_metric('transactions', values, @tags)
|
||||
end
|
||||
|
||||
def submit
|
||||
Metrics.submit_metrics(@metrics.map(&:to_hash))
|
||||
end
|
||||
|
||||
def sidekiq?
|
||||
Sidekiq.server?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,76 +1,46 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe AbuseReportsController do
|
||||
let(:reporter) { create(:user) }
|
||||
let(:user) { create(:user) }
|
||||
let(:message) { "This user is a spammer" }
|
||||
let(:reporter) { create(:user) }
|
||||
let(:user) { create(:user) }
|
||||
let(:attrs) do
|
||||
attributes_for(:abuse_report) do |hash|
|
||||
hash[:user_id] = user.id
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in(reporter)
|
||||
end
|
||||
|
||||
describe "POST create" do
|
||||
context "with admin notification email set" do
|
||||
let(:admin_email) { "admin@example.com"}
|
||||
|
||||
before(:each) do
|
||||
stub_application_setting(admin_notification_email: admin_email)
|
||||
describe 'POST create' do
|
||||
context 'with valid attributes' do
|
||||
it 'saves the abuse report' do
|
||||
expect do
|
||||
post :create, abuse_report: attrs
|
||||
end.to change { AbuseReport.count }.by(1)
|
||||
end
|
||||
|
||||
it "sends a notification email" do
|
||||
perform_enqueued_jobs do
|
||||
post :create,
|
||||
abuse_report: {
|
||||
user_id: user.id,
|
||||
message: message
|
||||
}
|
||||
it 'calls notify' do
|
||||
expect_any_instance_of(AbuseReport).to receive(:notify)
|
||||
|
||||
email = ActionMailer::Base.deliveries.last
|
||||
|
||||
expect(email.to).to eq([admin_email])
|
||||
expect(email.subject).to include(user.username)
|
||||
expect(email.text_part.body).to include(message)
|
||||
end
|
||||
post :create, abuse_report: attrs
|
||||
end
|
||||
|
||||
it "saves the abuse report" do
|
||||
perform_enqueued_jobs do
|
||||
expect do
|
||||
post :create,
|
||||
abuse_report: {
|
||||
user_id: user.id,
|
||||
message: message
|
||||
}
|
||||
end.to change { AbuseReport.count }.by(1)
|
||||
end
|
||||
it 'redirects back to the reported user' do
|
||||
post :create, abuse_report: attrs
|
||||
|
||||
expect(response).to redirect_to user
|
||||
end
|
||||
end
|
||||
|
||||
context "without admin notification email set" do
|
||||
before(:each) do
|
||||
stub_application_setting(admin_notification_email: nil)
|
||||
end
|
||||
context 'with invalid attributes' do
|
||||
it 'renders new' do
|
||||
attrs.delete(:user_id)
|
||||
post :create, abuse_report: attrs
|
||||
|
||||
it "does not send a notification email" do
|
||||
expect do
|
||||
post :create,
|
||||
abuse_report: {
|
||||
user_id: user.id,
|
||||
message: message
|
||||
}
|
||||
end.not_to change { ActionMailer::Base.deliveries.count }
|
||||
end
|
||||
|
||||
it "saves the abuse report" do
|
||||
expect do
|
||||
post :create,
|
||||
abuse_report: {
|
||||
user_id: user.id,
|
||||
message: message
|
||||
}
|
||||
end.to change { AbuseReport.count }.by(1)
|
||||
expect(response).to render_template(:new)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,69 +1,98 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Admin Builds" do
|
||||
let(:commit) { FactoryGirl.create :ci_commit }
|
||||
let(:build) { FactoryGirl.create :ci_build, commit: commit }
|
||||
|
||||
describe 'Admin Builds' do
|
||||
before do
|
||||
login_as :admin
|
||||
end
|
||||
|
||||
describe "GET /admin/builds" do
|
||||
before do
|
||||
build
|
||||
visit admin_builds_path
|
||||
end
|
||||
describe 'GET /admin/builds' do
|
||||
let(:commit) { create(:ci_commit) }
|
||||
|
||||
it { expect(page).to have_content "Running" }
|
||||
it { expect(page).to have_content build.short_sha }
|
||||
end
|
||||
context 'All tab' do
|
||||
context 'when have builds' do
|
||||
it 'shows all builds' do
|
||||
create(:ci_build, commit: commit, status: :pending)
|
||||
create(:ci_build, commit: commit, status: :running)
|
||||
create(:ci_build, commit: commit, status: :success)
|
||||
create(:ci_build, commit: commit, status: :failed)
|
||||
|
||||
describe "Tabs" do
|
||||
it "shows all builds" do
|
||||
FactoryGirl.create :ci_build, commit: commit, status: "pending"
|
||||
FactoryGirl.create :ci_build, commit: commit, status: "running"
|
||||
FactoryGirl.create :ci_build, commit: commit, status: "success"
|
||||
FactoryGirl.create :ci_build, commit: commit, status: "failed"
|
||||
visit admin_builds_path
|
||||
|
||||
visit admin_builds_path
|
||||
|
||||
within ".center-top-menu" do
|
||||
click_on "All"
|
||||
expect(page).to have_selector('.project-issuable-filter li.active', text: 'All')
|
||||
expect(page.all('.build-link').size).to eq(4)
|
||||
expect(page).to have_link 'Cancel all'
|
||||
end
|
||||
end
|
||||
|
||||
expect(page.all(".build-link").size).to eq(4)
|
||||
context 'when have no builds' do
|
||||
it 'shows a message' do
|
||||
visit admin_builds_path
|
||||
|
||||
expect(page).to have_selector('.project-issuable-filter li.active', text: 'All')
|
||||
expect(page).to have_content 'No builds to show'
|
||||
expect(page).not_to have_link 'Cancel all'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "shows finished builds" do
|
||||
build = FactoryGirl.create :ci_build, commit: commit, status: "pending"
|
||||
build1 = FactoryGirl.create :ci_build, commit: commit, status: "running"
|
||||
build2 = FactoryGirl.create :ci_build, commit: commit, status: "success"
|
||||
context 'Running tab' do
|
||||
context 'when have running builds' do
|
||||
it 'shows running builds' do
|
||||
build1 = create(:ci_build, commit: commit, status: :pending)
|
||||
build2 = create(:ci_build, commit: commit, status: :success)
|
||||
build3 = create(:ci_build, commit: commit, status: :failed)
|
||||
|
||||
visit admin_builds_path
|
||||
visit admin_builds_path(scope: :running)
|
||||
|
||||
within ".center-top-menu" do
|
||||
click_on "Finished"
|
||||
expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running')
|
||||
expect(page.find('.build-link')).to have_content(build1.id)
|
||||
expect(page.find('.build-link')).not_to have_content(build2.id)
|
||||
expect(page.find('.build-link')).not_to have_content(build3.id)
|
||||
expect(page).to have_link 'Cancel all'
|
||||
end
|
||||
end
|
||||
|
||||
expect(page.find(".build-link")).not_to have_content(build.id)
|
||||
expect(page.find(".build-link")).not_to have_content(build1.id)
|
||||
expect(page.find(".build-link")).to have_content(build2.id)
|
||||
context 'when have no builds running' do
|
||||
it 'shows a message' do
|
||||
create(:ci_build, commit: commit, status: :success)
|
||||
|
||||
visit admin_builds_path(scope: :running)
|
||||
|
||||
expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running')
|
||||
expect(page).to have_content 'No builds to show'
|
||||
expect(page).not_to have_link 'Cancel all'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "shows running builds" do
|
||||
build = FactoryGirl.create :ci_build, commit: commit, status: "pending"
|
||||
build2 = FactoryGirl.create :ci_build, commit: commit, status: "success"
|
||||
build3 = FactoryGirl.create :ci_build, commit: commit, status: "failed"
|
||||
context 'Finished tab' do
|
||||
context 'when have finished builds' do
|
||||
it 'shows finished builds' do
|
||||
build1 = create(:ci_build, commit: commit, status: :pending)
|
||||
build2 = create(:ci_build, commit: commit, status: :running)
|
||||
build3 = create(:ci_build, commit: commit, status: :success)
|
||||
|
||||
visit admin_builds_path
|
||||
visit admin_builds_path(scope: :finished)
|
||||
|
||||
within ".center-top-menu" do
|
||||
click_on "Running"
|
||||
expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished')
|
||||
expect(page.find('.build-link')).not_to have_content(build1.id)
|
||||
expect(page.find('.build-link')).not_to have_content(build2.id)
|
||||
expect(page.find('.build-link')).to have_content(build3.id)
|
||||
expect(page).to have_link 'Cancel all'
|
||||
end
|
||||
end
|
||||
|
||||
expect(page.find(".build-link")).to have_content(build.id)
|
||||
expect(page.find(".build-link")).not_to have_content(build2.id)
|
||||
expect(page.find(".build-link")).not_to have_content(build3.id)
|
||||
context 'when have no builds finished' do
|
||||
it 'shows a message' do
|
||||
create(:ci_build, commit: commit, status: :running)
|
||||
|
||||
visit admin_builds_path(scope: :finished)
|
||||
|
||||
expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished')
|
||||
expect(page).to have_content 'No builds to show'
|
||||
expect(page).to have_link 'Cancel all'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,11 +15,11 @@ describe "Builds" do
|
|||
context "Running scope" do
|
||||
before do
|
||||
@build.run!
|
||||
visit namespace_project_builds_path(@project.namespace, @project)
|
||||
visit namespace_project_builds_path(@project.namespace, @project, scope: :running)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'Running' }
|
||||
it { expect(page).to have_content 'Cancel running' }
|
||||
it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running') }
|
||||
it { expect(page).to have_link 'Cancel running' }
|
||||
it { expect(page).to have_content @build.short_sha }
|
||||
it { expect(page).to have_content @build.ref }
|
||||
it { expect(page).to have_content @build.name }
|
||||
|
@ -31,21 +31,22 @@ describe "Builds" do
|
|||
visit namespace_project_builds_path(@project.namespace, @project, scope: :finished)
|
||||
end
|
||||
|
||||
it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished') }
|
||||
it { expect(page).to have_content 'No builds to show' }
|
||||
it { expect(page).to have_content 'Cancel running' }
|
||||
it { expect(page).to have_link 'Cancel running' }
|
||||
end
|
||||
|
||||
context "All builds" do
|
||||
before do
|
||||
@project.builds.running_or_pending.each(&:success)
|
||||
visit namespace_project_builds_path(@project.namespace, @project, scope: :all)
|
||||
visit namespace_project_builds_path(@project.namespace, @project)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'All' }
|
||||
it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') }
|
||||
it { expect(page).to have_content @build.short_sha }
|
||||
it { expect(page).to have_content @build.ref }
|
||||
it { expect(page).to have_content @build.name }
|
||||
it { expect(page).to_not have_content 'Cancel running' }
|
||||
it { expect(page).to_not have_link 'Cancel running' }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -56,8 +57,12 @@ describe "Builds" do
|
|||
click_link "Cancel running"
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'No builds to show' }
|
||||
it { expect(page).to_not have_content 'Cancel running' }
|
||||
it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') }
|
||||
it { expect(page).to have_content 'canceled' }
|
||||
it { expect(page).to have_content @build.short_sha }
|
||||
it { expect(page).to have_content @build.ref }
|
||||
it { expect(page).to have_content @build.name }
|
||||
it { expect(page).to_not have_link 'Cancel running' }
|
||||
end
|
||||
|
||||
describe "GET /:project/builds/:id" do
|
||||
|
|
|
@ -80,8 +80,10 @@ feature 'Project', feature: true do
|
|||
visit namespace_project_path(project.namespace, project)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content('You have Master access to this project.') }
|
||||
it { expect(page).to have_link('Leave this project') }
|
||||
it 'click project-settings and find leave project' do
|
||||
find('#project-settings-button').click
|
||||
expect(page).to have_link('Leave Project')
|
||||
end
|
||||
end
|
||||
|
||||
def remove_with_confirm(button_text, confirm_with)
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe GroupsFinder do
|
||||
describe '#execute' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
let(:group1) { create(:group) }
|
||||
let(:group2) { create(:group) }
|
||||
let(:group3) { create(:group) }
|
||||
let(:group4) { create(:group, public: true) }
|
||||
|
||||
let!(:public_project) { create(:project, :public, group: group1) }
|
||||
let!(:internal_project) { create(:project, :internal, group: group2) }
|
||||
let!(:private_project) { create(:project, :private, group: group3) }
|
||||
|
||||
let(:finder) { described_class.new }
|
||||
|
||||
describe 'with a user' do
|
||||
subject { finder.execute(user) }
|
||||
|
||||
describe 'when the user is not a member of any groups' do
|
||||
it { is_expected.to eq([group4, group2, group1]) }
|
||||
end
|
||||
|
||||
describe 'when the user is a member of a group' do
|
||||
before do
|
||||
group3.add_user(user, Gitlab::Access::DEVELOPER)
|
||||
end
|
||||
|
||||
it { is_expected.to eq([group4, group3, group2, group1]) }
|
||||
end
|
||||
|
||||
describe 'when the user is a member of a private project' do
|
||||
before do
|
||||
private_project.team.add_user(user, Gitlab::Access::DEVELOPER)
|
||||
end
|
||||
|
||||
it { is_expected.to eq([group4, group3, group2, group1]) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'without a user' do
|
||||
subject { finder.execute }
|
||||
|
||||
it { is_expected.to eq([group4, group1]) }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,49 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe JoinedGroupsFinder do
|
||||
describe '#execute' do
|
||||
let(:source_user) { create(:user) }
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
let(:group1) { create(:group) }
|
||||
let(:group2) { create(:group) }
|
||||
let(:group3) { create(:group) }
|
||||
let(:group4) { create(:group, public: true) }
|
||||
|
||||
let!(:public_project) { create(:project, :public, group: group1) }
|
||||
let!(:internal_project) { create(:project, :internal, group: group2) }
|
||||
let!(:private_project) { create(:project, :private, group: group3) }
|
||||
|
||||
let(:finder) { described_class.new(source_user) }
|
||||
|
||||
before do
|
||||
[group1, group2, group3, group4].each do |group|
|
||||
group.add_user(source_user, Gitlab::Access::MASTER)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a current user' do
|
||||
describe 'when the current user has access to the projects of the source user' do
|
||||
before do
|
||||
private_project.team.add_user(current_user, Gitlab::Access::DEVELOPER)
|
||||
end
|
||||
|
||||
subject { finder.execute(current_user) }
|
||||
|
||||
it { is_expected.to eq([group4, group3, group2, group1]) }
|
||||
end
|
||||
|
||||
describe 'when the current user does not have access to the projects of the source user' do
|
||||
subject { finder.execute(current_user) }
|
||||
|
||||
it { is_expected.to eq([group4, group2, group1]) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'without a current user' do
|
||||
subject { finder.execute }
|
||||
|
||||
it { is_expected.to eq([group4, group1]) }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -43,7 +43,7 @@ describe SearchHelper do
|
|||
end
|
||||
|
||||
it "includes the public group" do
|
||||
group = create(:group, public: true)
|
||||
group = create(:group)
|
||||
expect(search_autocomplete_opts(group.name).size).to eq(1)
|
||||
end
|
||||
|
||||
|
|
|
@ -92,6 +92,14 @@ describe Banzai::Filter::RelativeLinkFilter, lib: true do
|
|||
to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
|
||||
end
|
||||
|
||||
it 'rebuilds relative URL for a file in the repository root' do
|
||||
relative_link = link('../README.md')
|
||||
doc = filter(relative_link, requested_path: 'doc/some-file.md')
|
||||
|
||||
expect(doc.at_css('a')['href']).
|
||||
to eq "/#{project_path}/blob/#{ref}/README.md"
|
||||
end
|
||||
|
||||
it 'rebuilds relative URL for a file in the repo with an anchor' do
|
||||
doc = filter(link('README.md#section'))
|
||||
expect(doc.at_css('a')['href']).
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Banzai::Querying do
|
||||
describe '.css' do
|
||||
it 'optimizes queries for elements with classes' do
|
||||
document = double(:document)
|
||||
|
||||
expect(document).to receive(:xpath).with(/^descendant::a/)
|
||||
|
||||
described_class.css(document, 'a.gfm')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -48,6 +48,9 @@ describe Gitlab::Metrics::Instrumentation do
|
|||
allow(described_class).to receive(:transaction).
|
||||
and_return(transaction)
|
||||
|
||||
expect(transaction).to receive(:increment).
|
||||
with(:method_duration, a_kind_of(Numeric))
|
||||
|
||||
expect(transaction).to receive(:add_metric).
|
||||
with(described_class::SERIES, an_instance_of(Hash),
|
||||
method: 'Dummy.foo')
|
||||
|
@ -102,6 +105,9 @@ describe Gitlab::Metrics::Instrumentation do
|
|||
allow(described_class).to receive(:transaction).
|
||||
and_return(transaction)
|
||||
|
||||
expect(transaction).to receive(:increment).
|
||||
with(:method_duration, a_kind_of(Numeric))
|
||||
|
||||
expect(transaction).to receive(:add_metric).
|
||||
with(described_class::SERIES, an_instance_of(Hash),
|
||||
method: 'Dummy#bar')
|
||||
|
|
|
@ -37,12 +37,6 @@ describe Gitlab::Metrics::Metric do
|
|||
|
||||
it 'includes the tags' do
|
||||
expect(hash[:tags]).to be_an_instance_of(Hash)
|
||||
|
||||
expect(hash[:tags][:hostname]).to be_an_instance_of(String)
|
||||
expect(hash[:tags][:ruby_engine]).to be_an_instance_of(String)
|
||||
expect(hash[:tags][:ruby_version]).to be_an_instance_of(String)
|
||||
expect(hash[:tags][:gitlab_version]).to be_an_instance_of(String)
|
||||
expect(hash[:tags][:process_type]).to be_an_instance_of(String)
|
||||
end
|
||||
|
||||
it 'includes the values' do
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue