Commit d4e9c758 authored by Valery Sizov's avatar Valery Sizov

Merge remote-tracking branch 'origin/master' into emoji-picker-search

parents 5da8c1f7 94a55045
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.4.0 (unreleased) v 8.4.0 (unreleased)
- Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu)
- Implement new UI for group page - Implement new UI for group page
- Implement search inside emoji picker - Implement search inside emoji picker
- Add project permissions to all project API endpoints (Stan Hu)
v 8.3.0 v 8.3.0
- Add CAS support (tduehr) - Add CAS support (tduehr)
......
...@@ -202,9 +202,9 @@ gem 'font-awesome-rails', '~> 4.2' ...@@ -202,9 +202,9 @@ gem 'font-awesome-rails', '~> 4.2'
gem 'gitlab_emoji', '~> 0.2.0' gem 'gitlab_emoji', '~> 0.2.0'
gem 'gon', '~> 6.0.1' gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2' gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 3.1.3' gem 'jquery-rails', '~> 4.0.0'
gem 'jquery-scrollto-rails', '~> 1.4.3' gem 'jquery-scrollto-rails', '~> 1.4.3'
gem 'jquery-ui-rails', '~> 4.2.1' gem 'jquery-ui-rails', '~> 5.0.0'
gem 'nprogress-rails', '~> 0.1.6.7' gem 'nprogress-rails', '~> 0.1.6.7'
gem 'raphael-rails', '~> 2.1.2' gem 'raphael-rails', '~> 2.1.2'
gem 'request_store', '~> 1.2.0' gem 'request_store', '~> 1.2.0'
......
...@@ -372,15 +372,16 @@ GEM ...@@ -372,15 +372,16 @@ GEM
inflecto (0.0.2) inflecto (0.0.2)
ipaddress (0.8.0) ipaddress (0.8.0)
jquery-atwho-rails (1.3.2) jquery-atwho-rails (1.3.2)
jquery-rails (3.1.4) jquery-rails (4.0.5)
railties (>= 3.0, < 5.0) rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
jquery-scrollto-rails (1.4.3) jquery-scrollto-rails (1.4.3)
railties (> 3.1, < 5.0) railties (> 3.1, < 5.0)
jquery-turbolinks (2.1.0) jquery-turbolinks (2.1.0)
railties (>= 3.1.0) railties (>= 3.1.0)
turbolinks turbolinks
jquery-ui-rails (4.2.1) jquery-ui-rails (5.0.5)
railties (>= 3.2.16) railties (>= 3.2.16)
json (1.8.3) json (1.8.3)
jwt (1.5.2) jwt (1.5.2)
...@@ -879,10 +880,10 @@ DEPENDENCIES ...@@ -879,10 +880,10 @@ DEPENDENCIES
html-pipeline (~> 1.11.0) html-pipeline (~> 1.11.0)
httparty (~> 0.13.3) httparty (~> 0.13.3)
jquery-atwho-rails (~> 1.3.2) jquery-atwho-rails (~> 1.3.2)
jquery-rails (~> 3.1.3) jquery-rails (~> 4.0.0)
jquery-scrollto-rails (~> 1.4.3) jquery-scrollto-rails (~> 1.4.3)
jquery-turbolinks (~> 2.1.0) jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 4.2.1) jquery-ui-rails (~> 5.0.0)
kaminari (~> 0.16.3) kaminari (~> 0.16.3)
letter_opener (~> 1.1.2) letter_opener (~> 1.1.2)
mail_room (~> 0.6.1) mail_room (~> 0.6.1)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# the compiled file. # the compiled file.
# #
#= require jquery #= require jquery
#= require jquery.ui.all #= require jquery-ui
#= require jquery_ujs #= require jquery_ujs
#= require jquery.cookie #= require jquery.cookie
#= require jquery.endless-scroll #= require jquery.endless-scroll
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* This is a manifest file that'll automatically include all the stylesheets available in this directory * This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope. * the top of the compiled file, but it's generally better to create a new file per style scope.
*= require jquery.ui.datepicker *= require jquery-ui/datepicker
*= require jquery.ui.autocomplete *= require jquery-ui/autocomplete
*= require jquery.atwho *= require jquery.atwho
*= require select2 *= require select2
*= require_self *= require_self
...@@ -48,4 +48,4 @@ ...@@ -48,4 +48,4 @@
/* /*
* Styles for JS behaviors. * Styles for JS behaviors.
*/ */
@import "behaviors.scss"; @import "behaviors.scss";
\ No newline at end of file
@mixin btn-default { @mixin btn-default {
@include border-radius(2px); @include border-radius(3px);
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
text-transform: uppercase; font-size: 15px;
font-size: 13px; font-weight: 500;
font-weight: 600;
line-height: 18px; line-height: 18px;
padding: 11px $gl-padding; padding: 11px $gl-padding;
letter-spacing: .4px; letter-spacing: .4px;
...@@ -18,7 +17,7 @@ ...@@ -18,7 +17,7 @@
@mixin btn-middle { @mixin btn-middle {
@include btn-default; @include btn-default;
@include border-radius(2px); @include border-radius(3px);
padding: 11px 24px; padding: 11px 24px;
} }
...@@ -51,6 +50,10 @@ ...@@ -51,6 +50,10 @@
@include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF); @include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF);
} }
@mixin btn-blue-medium {
@include btn-color($blue-medium-light, $border-blue-light, $blue-medium, $border-blue-normal, $blue-medium-dark, $border-blue-dark, #FFFFFF);
}
@mixin btn-orange { @mixin btn-orange {
@include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF); @include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF);
} }
...@@ -60,7 +63,7 @@ ...@@ -60,7 +63,7 @@
} }
@mixin btn-gray { @mixin btn-gray {
@include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, #313236); @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-light, $gray-dark, $border-gray-dark, #313236);
} }
@mixin btn-white { @mixin btn-white {
...@@ -75,6 +78,10 @@ ...@@ -75,6 +78,10 @@
padding: 5px 10px; padding: 5px 10px;
} }
&.btn-nr {
padding: 7px 10px;
}
&.btn-xs { &.btn-xs {
padding: 1px 5px; padding: 1px 5px;
} }
...@@ -91,11 +98,15 @@ ...@@ -91,11 +98,15 @@
@include btn-gray; @include btn-gray;
} }
&.btn-primary, &.btn-primary {
@include btn-blue-medium;
}
&.btn-info { &.btn-info {
@include btn-blue; @include btn-blue;
} }
&.btn-close,
&.btn-warning { &.btn-warning {
@include btn-orange; @include btn-orange;
} }
...@@ -110,20 +121,8 @@ ...@@ -110,20 +121,8 @@
float: right; float: right;
} }
&.btn-close {
color: $gl-danger;
border-color: $gl-danger;
&:hover {
color: #B94A48;
}
}
&.btn-reopen { &.btn-reopen {
color: $gl-success; /* should be same as parent class for now */
border-color: $gl-success;
&:hover {
color: #468847;
}
} }
&.btn-grouped { &.btn-grouped {
......
...@@ -374,7 +374,7 @@ table { ...@@ -374,7 +374,7 @@ table {
} }
} }
.center-top-menu { .center-top-menu, .left-top-menu {
@include nav-menu; @include nav-menu;
text-align: center; text-align: center;
margin-top: 5px; margin-top: 5px;
...@@ -408,6 +408,11 @@ table { ...@@ -408,6 +408,11 @@ table {
} }
} }
.left-top-menu {
text-align: left;
border-bottom: 1px solid #EEE;
}
.center-middle-menu { .center-middle-menu {
@include nav-menu; @include nav-menu;
padding: 0; padding: 0;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
.status-box { .status-box {
@include border-radius(2px); @include border-radius(3px);
display: block; display: block;
float: left; float: left;
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
} }
&.status-box-open { &.status-box-open {
background-color: #019875; background-color: $green-light;
color: #FFF; color: #FFF;
} }
......
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
display: none; display: none;
} }
.center-top-menu { .center-top-menu, .left-top-menu {
li a { li a {
font-size: 14px; font-size: 14px;
padding: 19px 10px; padding: 19px 10px;
......
...@@ -45,6 +45,10 @@ $blue-light: #2EA8E5; ...@@ -45,6 +45,10 @@ $blue-light: #2EA8E5;
$blue-normal: #2D9FD8; $blue-normal: #2D9FD8;
$blue-dark: #2897CE; $blue-dark: #2897CE;
$blue-medium-light: #3498CB;
$blue-medium: #2F8EBF;
$blue-medium-dark: #2D86B4;
$orange-light: #FC6443; $orange-light: #FC6443;
$orange-normal: #E75E40; $orange-normal: #E75E40;
$orange-dark: #CE5237; $orange-dark: #CE5237;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
color: #5c5d5e; color: #5c5d5e;
font-size: 16px; font-size: 16px;
line-height: 42px; line-height: 34px;
.author { .author {
color: #5c5d5e; color: #5c5d5e;
......
...@@ -75,16 +75,15 @@ ...@@ -75,16 +75,15 @@
.common-note-form { .common-note-form {
margin: 0; margin: 0;
background: #F7F8FA; background: #fff;
padding: $gl-padding; padding: $gl-padding;
margin-left: -$gl-padding; margin-left: -$gl-padding;
margin-right: -$gl-padding; margin-right: -$gl-padding;
border-top: 1px solid $border-color;
margin-bottom: -$gl-padding; margin-bottom: -$gl-padding;
} }
.note-form-actions { .note-form-actions {
background: #F9F9F9; background: #fff;
.note-form-option { .note-form-option {
margin-top: 8px; margin-top: 8px;
......
...@@ -128,7 +128,7 @@ ul.notes { ...@@ -128,7 +128,7 @@ ul.notes {
} }
&:last-child { &:last-child {
border-bottom: none; border-bottom: 1px solid $border-color;
} }
} }
} }
......
...@@ -335,6 +335,36 @@ ul.nav.nav-projects-tabs { ...@@ -335,6 +335,36 @@ ul.nav.nav-projects-tabs {
} }
} }
.top-area {
border-bottom: 1px solid #EEE;
ul.left-top-menu {
display: inline-block;
width: 50%;
margin-bottom: 0px;
border-bottom: none;
}
.projects-search-form {
width: 50%;
display: inline-block;
float: right;
padding-top: 7px;
text-align: right;
.btn-green {
margin-top: -2px;
margin-left: 10px;
}
}
@media (max-width: $screen-xs-max) {
.projects-search-form {
padding-top: 15px;
}
}
}
.fork-namespaces { .fork-namespaces {
.fork-thumbnail { .fork-thumbnail {
text-align: center; text-align: center;
...@@ -412,11 +442,18 @@ pre.light-well { ...@@ -412,11 +442,18 @@ pre.light-well {
.projects-search-form { .projects-search-form {
margin: -$gl-padding; margin: -$gl-padding;
background-color: #f8fafc;
padding: $gl-padding; padding: $gl-padding;
margin-bottom: 0px; margin-bottom: 0px;
border-top: 1px solid #e7e9ed;
border-bottom: 1px solid #e7e9ed; input {
display: inline-block;
width: calc(100% - 151px);
}
.btn {
display: inline-block;
width: 135px;
}
} }
.git-empty { .git-empty {
......
...@@ -134,4 +134,8 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -134,4 +134,8 @@ class ApplicationSetting < ActiveRecord::Base
/x) /x)
self.restricted_signup_domains.reject! { |d| d.empty? } self.restricted_signup_domains.reject! { |d| d.empty? }
end end
def runners_registration_token
ensure_runners_registration_token!
end
end end
...@@ -18,15 +18,16 @@ module TokenAuthenticatable ...@@ -18,15 +18,16 @@ module TokenAuthenticatable
define_method("ensure_#{token_field}") do define_method("ensure_#{token_field}") do
current_token = read_attribute(token_field) current_token = read_attribute(token_field)
if current_token.blank? current_token.blank? ? write_new_token(token_field) : current_token
write_attribute(token_field, generate_token_for(token_field)) end
else
current_token define_method("ensure_#{token_field}!") do
end send("reset_#{token_field}!") if read_attribute(token_field).blank?
read_attribute(token_field)
end end
define_method("reset_#{token_field}!") do define_method("reset_#{token_field}!") do
write_attribute(token_field, generate_token_for(token_field)) write_new_token(token_field)
save! save!
end end
end end
...@@ -34,7 +35,12 @@ module TokenAuthenticatable ...@@ -34,7 +35,12 @@ module TokenAuthenticatable
private private
def generate_token_for(token_field) def write_new_token(token_field)
new_token = generate_token(token_field)
write_attribute(token_field, new_token)
end
def generate_token(token_field)
loop do loop do
token = Devise.friendly_token token = Devise.friendly_token
break token unless self.class.unscoped.find_by(token_field => token) break token unless self.class.unscoped.find_by(token_field => token)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
To register a new runner you should enter the following registration token. To register a new runner you should enter the following registration token.
With this token the runner will request a unique runner token and use that for future communication. With this token the runner will request a unique runner token and use that for future communication.
Registration token is Registration token is
%code{ id: 'runners-token' } #{current_application_settings.ensure_runners_registration_token} %code{ id: 'runners-token' } #{current_application_settings.runners_registration_token}
.bs-callout.clearfix .bs-callout.clearfix
.pull-left .pull-left
......
= content_for :flash_message do = content_for :flash_message do
= render 'shared/project_limit' = render 'shared/project_limit'
.top-area
%ul.left-top-menu
= nav_link(page: [dashboard_projects_path, root_path]) do
= link_to dashboard_projects_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do
Your Projects
= nav_link(page: starred_dashboard_projects_path) do
= link_to starred_dashboard_projects_path, title: 'Starred Projects', data: {placement: 'right'} do
Starred Projects
= nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path], html_options: { class: 'hidden-xs' }) do
= link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do
Explore Projects
%ul.center-top-menu .projects-search-form
= nav_link(page: [dashboard_projects_path, root_path]) do = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs', spellcheck: false
= link_to dashboard_projects_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do - if current_user.can_create_project?
Your Projects = link_to new_project_path, class: 'btn btn-green' do
= nav_link(page: starred_dashboard_projects_path) do %i.fa.fa-plus
= link_to starred_dashboard_projects_path, title: 'Starred Projects', data: {placement: 'right'} do New Project
Starred Projects
= nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path], html_options: { class: 'hidden-xs' }) do
= link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do
Explore Projects
.projects-list-holder .projects-list-holder
.projects-search-form
.input-group
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
- if current_user.can_create_project?
%span.input-group-btn
= link_to new_project_path, class: 'btn btn-green' do
%i.fa.fa-plus
New Project
= render 'shared/projects/list', projects: @projects, ci: true = render 'shared/projects/list', projects: @projects, ci: true
- content_for :note_actions do - content_for :note_actions do
- if can?(current_user, :update_issue, @issue) - if can?(current_user, :update_issue, @issue)
- if @issue.closed? - if @issue.closed?
= link_to 'Reopen Issue', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-grouped btn-reopen js-note-target-reopen', title: 'Reopen Issue' = link_to 'Reopen Issue', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-nr btn-grouped btn-reopen js-note-target-reopen', title: 'Reopen Issue'
- else - else
= link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close js-note-target-close', title: 'Close Issue' = link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-nr btn-grouped btn-close js-note-target-close', title: 'Close Issue'
#notes #notes
= render 'projects/notes/notes_with_form' = render 'projects/notes/notes_with_form'
...@@ -23,16 +23,16 @@ ...@@ -23,16 +23,16 @@
.pull-right .pull-right
- if can?(current_user, :create_issue, @project) - if can?(current_user, :create_issue, @project)
= link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-grouped new-issue-link', title: 'New Issue', id: 'new_issue_link' do = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-nr btn-grouped new-issue-link btn-success', title: 'New Issue', id: 'new_issue_link' do
= icon('plus') = icon('plus')
New Issue New Issue
- if can?(current_user, :update_issue, @issue) - if can?(current_user, :update_issue, @issue)
- if @issue.closed? - if @issue.closed?
= link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-grouped btn-reopen' = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-nr btn-grouped btn-reopen'
- else - else
= link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close', title: 'Close Issue' = link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-nr btn-grouped btn-close', title: 'Close Issue'
= link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-grouped issuable-edit' do = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-nr btn-grouped issuable-edit' do
= icon('pencil-square-o') = icon('pencil-square-o')
Edit Edit
......
- content_for :note_actions do - content_for :note_actions do
- if can?(current_user, :update_merge_request, @merge_request) - if can?(current_user, :update_merge_request, @merge_request)
- if @merge_request.open? - if @merge_request.open?
= link_to 'Close', merge_request_path(@merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close close-mr-link js-note-target-close", title: "Close merge request" = link_to 'Close', merge_request_path(@merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-nr btn-grouped btn-close close-mr-link js-note-target-close", title: "Close merge request"
- if @merge_request.closed? - if @merge_request.closed?
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request" = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-nr btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request"
#notes= render "projects/notes/notes_with_form" #notes= render "projects/notes/notes_with_form"
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
.issue-btn-group.pull-right .issue-btn-group.pull-right
- if can?(current_user, :update_merge_request, @merge_request) - if can?(current_user, :update_merge_request, @merge_request)
- if @merge_request.open? - if @merge_request.open?
= link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: 'btn btn-grouped btn-close', title: 'Close merge request' = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: 'btn btn-nr btn-grouped btn-close', title: 'Close merge request'
= link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'btn btn-grouped issuable-edit', id: 'edit_merge_request' do = link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'btn btn-nr btn-grouped issuable-edit', id: 'edit_merge_request' do
%i.fa.fa-pencil-square-o %i.fa.fa-pencil-square-o
Edit Edit
- if @merge_request.closed? - if @merge_request.closed?
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'btn btn-grouped btn-reopen reopen-mr-link', title: 'Reopen merge request' = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'btn btn-nr btn-grouped btn-reopen reopen-mr-link', title: 'Reopen merge request'
...@@ -13,6 +13,6 @@ ...@@ -13,6 +13,6 @@
.error-alert .error-alert
.note-form-actions.clearfix .note-form-actions.clearfix
= f.submit 'Add Comment', class: "btn btn-create comment-btn btn-grouped js-comment-button" = f.submit 'Add Comment', class: "btn btn-nr btn-create comment-btn btn-grouped js-comment-button"
= yield(:note_actions) = yield(:note_actions)
%a.btn.btn-cancel.js-close-discussion-note-form Cancel %a.btn.btn-cancel.js-close-discussion-note-form Cancel
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
- if issue.description.present? - if issue.description.present?
.description.term .description.term
= preserve do = preserve do
= search_md_sanitize(markdown(issue.description)) = search_md_sanitize(markdown(issue.description, { project: issue.project }))
%span.light %span.light
#{issue.project.name_with_namespace} #{issue.project.name_with_namespace}
- if issue.closed? - if issue.closed?
......
class AddBuildEventsToServices < ActiveRecord::Migration class AddBuildEventsToServices < ActiveRecord::Migration
def up def change
add_column :services, :build_events, :boolean, default: false, null: false add_column :services, :build_events, :boolean, default: false, null: false
add_column :web_hooks, :build_events, :boolean, default: false, null: false add_column :web_hooks, :build_events, :boolean, default: false, null: false
end end
......
...@@ -10,4 +10,7 @@ class MigrateCiWebHooks < ActiveRecord::Migration ...@@ -10,4 +10,7 @@ class MigrateCiWebHooks < ActiveRecord::Migration
'JOIN projects ON ci_projects.gitlab_id = projects.id' 'JOIN projects ON ci_projects.gitlab_id = projects.id'
) )
end end
def down
end
end end
class AddCiToProject < ActiveRecord::Migration class AddCiToProject < ActiveRecord::Migration
def up def change
add_column :projects, :ci_id, :integer add_column :projects, :ci_id, :integer
add_column :projects, :builds_enabled, :boolean, default: true, null: false add_column :projects, :builds_enabled, :boolean, default: true, null: false
add_column :projects, :shared_runners_enabled, :boolean, default: true, null: false add_column :projects, :shared_runners_enabled, :boolean, default: true, null: false
......
class AddProjectIdToCi < ActiveRecord::Migration class AddProjectIdToCi < ActiveRecord::Migration
def up def change
add_column :ci_builds, :gl_project_id, :integer add_column :ci_builds, :gl_project_id, :integer
add_column :ci_runner_projects, :gl_project_id, :integer add_column :ci_runner_projects, :gl_project_id, :integer
add_column :ci_triggers, :gl_project_id, :integer add_column :ci_triggers, :gl_project_id, :integer
......
...@@ -14,6 +14,10 @@ class MigrateCiToProject < ActiveRecord::Migration ...@@ -14,6 +14,10 @@ class MigrateCiToProject < ActiveRecord::Migration
migrate_ci_service migrate_ci_service
end end
def down
# We can't reverse the data
end
def migrate_project_id_for_table(table) def migrate_project_id_for_table(table)
subquery = "SELECT gitlab_id FROM ci_projects WHERE ci_projects.id = #{table}.project_id" subquery = "SELECT gitlab_id FROM ci_projects WHERE ci_projects.id = #{table}.project_id"
execute("UPDATE #{table} SET gl_project_id=(#{subquery}) WHERE gl_project_id IS NULL") execute("UPDATE #{table} SET gl_project_id=(#{subquery}) WHERE gl_project_id IS NULL")
......
class AddIndexToCiTables < ActiveRecord::Migration class AddIndexToCiTables < ActiveRecord::Migration
def up def change
add_index :ci_builds, :gl_project_id add_index :ci_builds, :gl_project_id
add_index :ci_runner_projects, :gl_project_id add_index :ci_runner_projects, :gl_project_id
add_index :ci_triggers, :gl_project_id add_index :ci_triggers, :gl_project_id
......
class DropNullForCiTables < ActiveRecord::Migration class DropNullForCiTables < ActiveRecord::Migration
def up def change
remove_index :ci_variables, :project_id remove_index :ci_variables, :project_id
remove_index :ci_runner_projects, :project_id remove_index :ci_runner_projects, :project_id
change_column_null :ci_triggers, :project_id, true change_column_null :ci_triggers, :project_id, true
......
...@@ -118,6 +118,16 @@ Parameters: ...@@ -118,6 +118,16 @@ Parameters:
"path": "brightbox", "path": "brightbox",
"updated_at": "2013-09-30T13:46:02Z" "updated_at": "2013-09-30T13:46:02Z"
}, },
"permissions": {
"project_access": {
"access_level": 10,
"notification_level": 3
},
"group_access": {
"access_level": 50,
"notification_level": 3
}
},
"archived": false, "archived": false,
"avatar_url": null "avatar_url": null
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
### Examples ### Examples
+ [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)
+ [Test and deploy Ruby applications to Heroku](examples/test-and-deploy-ruby-application-to-heroku.md) + [Test and deploy Ruby applications to Heroku](examples/test-and-deploy-ruby-application-to-heroku.md)
+ [Test and deploy Python applications to Heroku](examples/test-and-deploy-python-application-to-heroku.md) + [Test and deploy Python applications to Heroku](examples/test-and-deploy-python-application-to-heroku.md)
+ [Test Clojure applications](examples/test-clojure-application.md) + [Test Clojure applications](examples/test-clojure-application.md)
......
...@@ -25,7 +25,7 @@ module API ...@@ -25,7 +25,7 @@ module API
@projects = current_user.authorized_projects @projects = current_user.authorized_projects
@projects = filter_projects(@projects) @projects = filter_projects(@projects)
@projects = paginate @projects @projects = paginate @projects
present @projects, with: Entities::Project present @projects, with: Entities::ProjectWithAccess, user: current_user
end end
# Get an owned projects list for authenticated user # Get an owned projects list for authenticated user
...@@ -36,7 +36,7 @@ module API ...@@ -36,7 +36,7 @@ module API
@projects = current_user.owned_projects @projects = current_user.owned_projects
@projects = filter_projects(@projects) @projects = filter_projects(@projects)
@projects = paginate @projects @projects = paginate @projects
present @projects, with: Entities::Project present @projects, with: Entities::ProjectWithAccess, user: current_user
end end
# Gets starred project for the authenticated user # Gets starred project for the authenticated user
...@@ -59,7 +59,7 @@ module API ...@@ -59,7 +59,7 @@ module API
@projects = Project.all @projects = Project.all
@projects = filter_projects(@projects) @projects = filter_projects(@projects)
@projects = paginate @projects @projects = paginate @projects
present @projects, with: Entities::Project present @projects, with: Entities::ProjectWithAccess, user: current_user
end end
# Get a single project # Get a single project
......
...@@ -19,7 +19,7 @@ module Ci ...@@ -19,7 +19,7 @@ module Ci
end end
def runner_registration_token_valid? def runner_registration_token_valid?
params[:token] == current_application_settings.ensure_runners_registration_token params[:token] == current_application_settings.runners_registration_token
end end
def update_runner_last_contact def update_runner_last_contact
......
...@@ -92,7 +92,7 @@ check_pids(){ ...@@ -92,7 +92,7 @@ check_pids(){
## Called when we have started the two processes and are waiting for their pid files. ## Called when we have started the two processes and are waiting for their pid files.
wait_for_pids(){ wait_for_pids(){
# We are sleeping a bit here mostly because sidekiq is slow at writing it's pid # We are sleeping a bit here mostly because sidekiq is slow at writing its pid
i=0; i=0;
while [ ! -f $web_server_pid_path ] || [ ! -f $sidekiq_pid_path ] || [ ! -f $gitlab_workhorse_pid_path ] || { [ "$mail_room_enabled" = true ] && [ ! -f $mail_room_pid_path ]; }; do while [ ! -f $web_server_pid_path ] || [ ! -f $sidekiq_pid_path ] || [ ! -f $gitlab_workhorse_pid_path ] || { [ "$mail_room_enabled" = true ] && [ ! -f $mail_room_pid_path ]; }; do
sleep 0.1; sleep 0.1;
...@@ -108,7 +108,7 @@ wait_for_pids(){ ...@@ -108,7 +108,7 @@ wait_for_pids(){
} }
# We use the pids in so many parts of the script it makes sense to always check them. # We use the pids in so many parts of the script it makes sense to always check them.
# Only after start() is run should the pids change. Sidekiq sets it's own pid. # Only after start() is run should the pids change. Sidekiq sets its own pid.
check_pids check_pids
...@@ -290,7 +290,7 @@ stop_gitlab() { ...@@ -290,7 +290,7 @@ stop_gitlab() {
sleep 1 sleep 1
# Cleaning up unused pids # Cleaning up unused pids
rm "$web_server_pid_path" 2>/dev/null rm "$web_server_pid_path" 2>/dev/null
# rm "$sidekiq_pid_path" 2>/dev/null # Sidekiq seems to be cleaning up it's own pid. # rm "$sidekiq_pid_path" 2>/dev/null # Sidekiq seems to be cleaning up its own pid.
rm -f "$gitlab_workhorse_pid_path" rm -f "$gitlab_workhorse_pid_path"
if [ "$mail_room_enabled" = true ]; then if [ "$mail_room_enabled" = true ]; then
rm "$mail_room_pid_path" 2>/dev/null rm "$mail_room_pid_path" 2>/dev/null
...@@ -299,7 +299,7 @@ stop_gitlab() { ...@@ -299,7 +299,7 @@ stop_gitlab() {
print_status print_status
} }
## Prints the status of GitLab and it's components. ## Prints the status of GitLab and its components.
print_status() { print_status() {
check_status check_status
if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && [ "$gitlab_workhorse_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && [ "$gitlab_workhorse_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then
...@@ -333,7 +333,7 @@ print_status() { ...@@ -333,7 +333,7 @@ print_status() {
fi fi
} }
## Tells unicorn to reload it's config and Sidekiq to restart ## Tells unicorn to reload its config and Sidekiq to restart
reload_gitlab(){ reload_gitlab(){
exit_if_not_running exit_if_not_running
if [ "$wpid" = "0" ];then if [ "$wpid" = "0" ];then
......
...@@ -9,11 +9,11 @@ RAILS_ENV="production" ...@@ -9,11 +9,11 @@ RAILS_ENV="production"
# The default is "git". # The default is "git".
app_user="git" app_user="git"
# app_root defines the folder in which gitlab and it's components are installed. # app_root defines the folder in which gitlab and its components are installed.
# The default is "/home/$app_user/gitlab" # The default is "/home/$app_user/gitlab"
app_root="/home/$app_user/gitlab" app_root="/home/$app_user/gitlab"
# pid_path defines a folder in which the gitlab and it's components place their pids. # pid_path defines a folder in which the gitlab and its components place their pids.
# This variable is also used below to define the relevant pids for the gitlab components. # This variable is also used below to define the relevant pids for the gitlab components.
# The default is "$app_root/tmp/pids" # The default is "$app_root/tmp/pids"
pid_path="$app_root/tmp/pids" pid_path="$app_root/tmp/pids"
......
...@@ -63,7 +63,7 @@ describe "Admin Runners" do ...@@ -63,7 +63,7 @@ describe "Admin Runners" do
end end
describe 'runners registration token' do describe 'runners registration token' do
let!(:token) { current_application_settings.ensure_runners_registration_token } let!(:token) { current_application_settings.runners_registration_token }
before { visit admin_runners_path } before { visit admin_runners_path }
it 'has a registration token' do it 'has a registration token' do
......
...@@ -2,7 +2,8 @@ require 'spec_helper' ...@@ -2,7 +2,8 @@ require 'spec_helper'
shared_examples 'TokenAuthenticatable' do shared_examples 'TokenAuthenticatable' do
describe 'dynamically defined methods' do describe 'dynamically defined methods' do
it { expect(described_class).to be_private_method_defined(:generate_token_for) } it { expect(described_class).to be_private_method_defined(:generate_token) }
it { expect(described_class).to be_private_method_defined(:write_new_token) }
it { expect(described_class).to respond_to("find_by_#{token_field}") } it { expect(described_class).to respond_to("find_by_#{token_field}") }
it { is_expected.to respond_to("ensure_#{token_field}") } it { is_expected.to respond_to("ensure_#{token_field}") }
it { is_expected.to respond_to("reset_#{token_field}!") } it { is_expected.to respond_to("reset_#{token_field}!") }
...@@ -24,11 +25,11 @@ describe ApplicationSetting, 'TokenAuthenticatable' do ...@@ -24,11 +25,11 @@ describe ApplicationSetting, 'TokenAuthenticatable' do
it_behaves_like 'TokenAuthenticatable' it_behaves_like 'TokenAuthenticatable'
describe 'generating new token' do describe 'generating new token' do
subject { described_class.new }
let(:token) { subject.send(token_field) }
context 'token is not generated yet' do context 'token is not generated yet' do
it { expect(token).to be nil } describe 'token field accessor' do
subject { described_class.new.send(token_field) }
it { is_expected.to_not be_blank }
end
describe 'ensured token' do describe 'ensured token' do
subject { described_class.new.send("ensure_#{token_field}") } subject { described_class.new.send("ensure_#{token_field}") }
...@@ -36,11 +37,21 @@ describe ApplicationSetting, 'TokenAuthenticatable' do ...@@ -36,11 +37,21 @@ describe ApplicationSetting, 'TokenAuthenticatable' do
it { is_expected.to be_a String } it { is_expected.to be_a String }
it { is_expected.to_not be_blank } it { is_expected.to_not be_blank }
end end
describe 'ensured! token' do
subject { described_class.new.send("ensure_#{token_field}!") }
it 'should persist new token' do
expect(subject).to eq described_class.current[token_field]
end
end
end end
context 'token is generated' do context 'token is generated' do
before { subject.send("reset_#{token_field}!") } before { subject.send("reset_#{token_field}!") }
it { expect(token).to be_a String } it 'persists a new token 'do
expect(subject.send(:read_attribute, token_field)).to be_a String
end
end end
end end
......
...@@ -131,6 +131,7 @@ describe API::API, api: true do ...@@ -131,6 +131,7 @@ describe API::API, api: true do
expect(json_response).to satisfy do |response| expect(json_response).to satisfy do |response|
response.one? do |entry| response.one? do |entry|
entry.has_key?('permissions') &&
entry['name'] == project.name && entry['name'] == project.name &&
entry['owner']['username'] == user.username entry['owner']['username'] == user.username
end end
...@@ -382,6 +383,18 @@ describe API::API, api: true do ...@@ -382,6 +383,18 @@ describe API::API, api: true do
end end
describe 'permissions' do describe 'permissions' do
context 'all projects' do
it 'Contains permission information' do
project.team << [user, :master]
get api("/projects", user)
expect(response.status).to eq(200)
expect(json_response.first['permissions']['project_access']['access_level']).
to eq(Gitlab::Access::MASTER)
expect(json_response.first['permissions']['group_access']).to be_nil
end
end
context 'personal project' do context 'personal project' do
it 'Sets project access and returns 200' do it 'Sets project access and returns 200' do
project.team << [user, :master] project.team << [user, :master]
......
...@@ -8,7 +8,6 @@ describe Ci::API::API do ...@@ -8,7 +8,6 @@ describe Ci::API::API do
before do before do
stub_gitlab_calls stub_gitlab_calls
stub_application_setting(ensure_runners_registration_token: registration_token)
stub_application_setting(runners_registration_token: registration_token) stub_application_setting(runners_registration_token: registration_token)
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment