Commit 423a39f0 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'master' into 8-0-stable

parents 08c8467f ca45e925
...@@ -22,7 +22,7 @@ gem "mysql2", '~> 0.3.16', group: :mysql ...@@ -22,7 +22,7 @@ gem "mysql2", '~> 0.3.16', group: :mysql
gem "pg", '~> 0.18.2', group: :postgres gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries # Authentication libraries
gem "devise", '~> 3.2.4' gem "devise", '~> 3.5.2'
gem "devise-async", '~> 0.9.0' gem "devise-async", '~> 0.9.0'
gem 'omniauth', "~> 1.2.2" gem 'omniauth', "~> 1.2.2"
gem 'omniauth-google-oauth2', '~> 0.2.5' gem 'omniauth-google-oauth2', '~> 0.2.5'
...@@ -38,7 +38,7 @@ gem 'omniauth_crowd' ...@@ -38,7 +38,7 @@ gem 'omniauth_crowd'
gem "rack-oauth2", "~> 1.0.5" gem "rack-oauth2", "~> 1.0.5"
# Two-factor authentication # Two-factor authentication
gem 'devise-two-factor', '~> 1.0.1' gem 'devise-two-factor', '~> 2.0.0'
gem 'rqrcode-rails3', '~> 0.1.7' gem 'rqrcode-rails3', '~> 0.1.7'
gem 'attr_encrypted', '~> 1.3.4' gem 'attr_encrypted', '~> 1.3.4'
......
...@@ -136,21 +136,21 @@ GEM ...@@ -136,21 +136,21 @@ GEM
activerecord (>= 3.2.0, < 5.0) activerecord (>= 3.2.0, < 5.0)
descendants_tracker (0.0.4) descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
devise (3.2.4) devise (3.5.2)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5) railties (>= 3.2.6, < 5)
responders
thread_safe (~> 0.1) thread_safe (~> 0.1)
warden (~> 1.2.3) warden (~> 1.2.3)
devise-async (0.9.0) devise-async (0.9.0)
devise (~> 3.2) devise (~> 3.2)
devise-two-factor (1.0.2) devise-two-factor (2.0.0)
activemodel
activesupport activesupport
attr_encrypted (~> 1.3.2) attr_encrypted (~> 1.3.2)
devise (>= 3.2.4, < 3.5) devise (~> 3.5.0)
railties railties
rotp (< 2) rotp (~> 2)
diff-lcs (1.2.5) diff-lcs (1.2.5)
diffy (3.0.7) diffy (3.0.7)
docile (1.1.5) docile (1.1.5)
...@@ -558,12 +558,14 @@ GEM ...@@ -558,12 +558,14 @@ GEM
request_store (1.2.0) request_store (1.2.0)
rerun (0.10.0) rerun (0.10.0)
listen (~> 2.7, >= 2.7.3) listen (~> 2.7, >= 2.7.3)
responders (1.1.2)
railties (>= 3.2, < 4.2)
rest-client (1.8.0) rest-client (1.8.0)
http-cookie (>= 1.0.2, < 2.0) http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0) mime-types (>= 1.16, < 3.0)
netrc (~> 0.7) netrc (~> 0.7)
rinku (1.7.3) rinku (1.7.3)
rotp (1.6.1) rotp (2.1.1)
rouge (1.10.1) rouge (1.10.1)
rqrcode (0.7.0) rqrcode (0.7.0)
chunky_png chunky_png
...@@ -806,9 +808,9 @@ DEPENDENCIES ...@@ -806,9 +808,9 @@ DEPENDENCIES
d3_rails (~> 3.5.5) d3_rails (~> 3.5.5)
database_cleaner (~> 1.4.0) database_cleaner (~> 1.4.0)
default_value_for (~> 3.0.0) default_value_for (~> 3.0.0)
devise (~> 3.2.4) devise (~> 3.5.2)
devise-async (~> 0.9.0) devise-async (~> 0.9.0)
devise-two-factor (~> 1.0.1) devise-two-factor (~> 2.0.0)
diffy (~> 3.0.3) diffy (~> 3.0.3)
doorkeeper (~> 2.1.3) doorkeeper (~> 2.1.3)
dropzonejs-rails (~> 0.7.1) dropzonejs-rails (~> 0.7.1)
...@@ -928,3 +930,6 @@ DEPENDENCIES ...@@ -928,3 +930,6 @@ DEPENDENCIES
webmock (~> 1.21.0) webmock (~> 1.21.0)
whenever (~> 0.8.4) whenever (~> 0.8.4)
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
BUNDLED WITH
1.10.6
...@@ -11,12 +11,13 @@ class @IssuableContext ...@@ -11,12 +11,13 @@ class @IssuableContext
$(this).submit() $(this).submit()
$('.issuable-details').waitForImages -> $('.issuable-details').waitForImages ->
$('.issuable-affix').on 'affix.bs.affix', ->
$(@).width($(@).outerWidth())
.on 'affixed-top.bs.affix affixed-bottom.bs.affix', ->
$(@).width('')
$('.issuable-affix').affix offset: $('.issuable-affix').affix offset:
top: -> top: ->
@top = ($('.issuable-affix').offset().top - 70) @top = ($('.issuable-affix').offset().top - 70)
bottom: -> bottom: ->
@bottom = $('.footer').outerHeight(true) @bottom = $('.footer').outerHeight(true)
$('.issuable-affix').on 'affix.bs.affix', ->
$(@).width($(@).outerWidth())
.on 'affixed-top.bs.affix affixed-bottom.bs.affix', ->
$(@).width('')
...@@ -65,20 +65,20 @@ $legend-color: $text-color; ...@@ -65,20 +65,20 @@ $legend-color: $text-color;
// //
//## //##
$pagination-color: #fff; $pagination-color: $gl-gray;
$pagination-bg: $brand-success; $pagination-bg: $background-color;
$pagination-border: transparent; $pagination-border: transparent;
$pagination-hover-color: #fff; $pagination-hover-color: #fff;
$pagination-hover-bg: darken($brand-success, 15%); $pagination-hover-bg: $brand-info;
$pagination-hover-border: transparent; $pagination-hover-border: transparent;
$pagination-active-color: #fff; $pagination-active-color: #fff;
$pagination-active-bg: darken($brand-success, 15%); $pagination-active-bg: $brand-info;
$pagination-active-border: transparent; $pagination-active-border: transparent;
$pagination-disabled-color: #b4bcc2; $pagination-disabled-color: #fff;
$pagination-disabled-bg: lighten($brand-success, 15%); $pagination-disabled-bg: lighten($brand-info, 15%);
$pagination-disabled-border: transparent; $pagination-disabled-border: transparent;
......
...@@ -13,31 +13,6 @@ ...@@ -13,31 +13,6 @@
.builds, .builds,
.projects-table { .projects-table {
.alert-success {
background-color: #6fc995;
border-color: #5bba83;
}
.alert-danger {
background-color: #eb897f;
border-color: #d4776e;
}
.alert-info {
background-color: #3498db;
border-color: #2e8ece;
}
.alert-warning {
background-color: #EB974E;
border-color: #E87E04;
}
.alert-disabled {
background: $background-color;
border-color: $border-color;
}
.light { .light {
border-color: $border-color; border-color: $border-color;
} }
...@@ -47,8 +22,8 @@ ...@@ -47,8 +22,8 @@
} }
td { td {
color: $gl-gray;
vertical-align: middle !important; vertical-align: middle !important;
border-color: inherit !important;
a { a {
font-weight: normal; font-weight: normal;
...@@ -58,23 +33,16 @@ ...@@ -58,23 +33,16 @@
} }
.commit-info { .commit-info {
font-size: 14px;
.attr-name { .attr-name {
font-weight: 300;
color: #666;
margin-right: 5px; margin-right: 5px;
} }
pre.commit-message { pre.commit-message {
font-size: 14px;
background: none; background: none;
padding: 0; padding: 0;
margin: 0; margin: 0;
border: none; border: none;
margin: 20px 0; margin: 20px 0;
border-bottom: 1px solid #EEE;
padding-bottom: 20px;
border-radius: 0; border-radius: 0;
} }
} }
...@@ -88,4 +56,38 @@ ...@@ -88,4 +56,38 @@
margin-bottom: 16px; margin-bottom: 16px;
} }
} }
.ci-status {
padding: 2px 7px;
margin-right: 5px;
border: 1px solid #EEE;
white-space: nowrap;
@include border-radius(4px);
&.ci-failed {
color: $gl-danger;
border-color: $gl-danger;
}
&.ci-success {
color: $gl-success;
border-color: $gl-success;
}
&.ci-info {
color: $gl-info;
border-color: $gl-info;
}
&.ci-disabled {
color: $gl-gray;
border-color: $gl-gray;
}
&.ci-pending,
&.ci-running {
color: $gl-warning;
border-color: $gl-warning;
}
}
} }
...@@ -20,11 +20,11 @@ ...@@ -20,11 +20,11 @@
.gray-content-block { .gray-content-block {
margin: -$gl-padding; margin: -$gl-padding;
background-color: #f8fafc; background-color: $background-color;
padding: $gl-padding; padding: $gl-padding;
margin-bottom: 0px; margin-bottom: 0px;
border-top: 1px solid #e7e9ed; border-top: 1px solid $border-color;
border-bottom: 1px solid #e7e9ed; border-bottom: 1px solid $border-color;
color: $gl-gray; color: $gl-gray;
&.top-block { &.top-block {
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
&.footer-block { &.footer-block {
margin-top: 0; margin-top: 0;
border-bottom: none;
margin-bottom: -$gl-padding; margin-bottom: -$gl-padding;
} }
......
/*
* Callouts from Bootstrap3 docs
*
* Not quite alerts, but custom and helpful notes for folks reading the docs.
* Requires a base and modifier class.
*/
/* Common styles for all types */
.bs-callout {
margin: 20px 0;
padding: 20px;
border-left: 3px solid #eee;
color: #666;
background: #f9f9f9;
}
.bs-callout h4 {
margin-top: 0;
margin-bottom: 5px;
}
.bs-callout p:last-child {
margin-bottom: 0;
}
/* Variations */
.bs-callout-danger {
background-color: #fdf7f7;
border-color: #eed3d7;
color: #b94a48;
}
.bs-callout-warning {
background-color: #faf8f0;
border-color: #faebcc;
color: #8a6d3b;
}
.bs-callout-info {
background-color: #f4f8fa;
border-color: #bce8f1;
color: #34789a;
}
.bs-callout-success {
background-color: #dff0d8;
border-color: #5cA64d;
color: #3c763d;
}
.gl-pagination {
border-top: 1px solid $border-color;
background-color: $background-color;
margin: -$gl-padding;
margin-top: 0;
.pagination {
padding: 0;
margin: 0;
display: block;
li.next,
li.prev {
> a {
color: $link-color;
&:hover {
color: #fff;
}
}
}
li > a,
li > span {
border: none;
margin: 0;
@include border-radius(0 !important);
padding: 13px 19px;
border-right: 1px solid $border-color;
}
}
}
...@@ -56,7 +56,7 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -56,7 +56,7 @@ class Admin::UsersController < Admin::ApplicationController
end end
def confirm def confirm
if user.confirm! if user.confirm
redirect_to :back, notice: "Successfully confirmed" redirect_to :back, notice: "Successfully confirmed"
else else
redirect_to :back, alert: "Error occurred. User was not confirmed" redirect_to :back, alert: "Error occurred. User was not confirmed"
......
...@@ -9,7 +9,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController ...@@ -9,7 +9,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
end end
def create def create
if current_user.valid_otp?(params[:pin_code]) if current_user.validate_and_consume_otp!(params[:pin_code])
current_user.two_factor_enabled = true current_user.two_factor_enabled = true
@codes = current_user.generate_otp_backup_codes! @codes = current_user.generate_otp_backup_codes!
current_user.save! current_user.save!
......
...@@ -99,7 +99,7 @@ class SessionsController < Devise::SessionsController ...@@ -99,7 +99,7 @@ class SessionsController < Devise::SessionsController
end end
def valid_otp_attempt?(user) def valid_otp_attempt?(user)
user.valid_otp?(user_params[:otp_attempt]) || user.validate_and_consume_otp!(user_params[:otp_attempt]) ||
user.invalidate_otp_backup_code!(user_params[:otp_attempt]) user.invalidate_otp_backup_code!(user_params[:otp_attempt])
end end
......
...@@ -28,5 +28,27 @@ module Ci ...@@ -28,5 +28,27 @@ module Ci
"#{pluralize(seconds, "second")}" "#{pluralize(seconds, "second")}"
end end
end end
def ci_icon_for_status(status)
icon_name =
case status
when 'success'
'check-square'
when 'failed'
'close'
when 'running', 'pending'
'clock-o'
else
'circle'
end
icon(icon_name)
end
def ci_status_with_icon(status)
content_tag :span, class: "ci-status ci-#{status}" do
ci_icon_for_status(status) + '&nbsp;'.html_safe + status
end
end
end end
end end
...@@ -15,27 +15,5 @@ module Ci ...@@ -15,27 +15,5 @@ module Ci
def build_url(build) def build_url(build)
ci_project_build_url(build.project, build) ci_project_build_url(build.project, build)
end end
def build_status_alert_class(build)
if build.success?
'alert-success'
elsif build.failed?
'alert-danger'
elsif build.canceled?
'alert-disabled'
else
'alert-warning'
end
end
def build_icon_css_class(build)
if build.success?
'fa-circle cgreen'
elsif build.failed?
'fa-circle cred'
else
'fa-circle light'
end
end
end end
end end
module Ci module Ci
module CommitsHelper module CommitsHelper
def commit_status_alert_class(commit)
return 'alert-info' unless commit
case commit.status
when 'success'
'alert-success'
when 'failed', 'canceled'
'alert-danger'
when 'skipped'
'alert-disabled'
else
'alert-warning'
end
end
def ci_commit_path(commit) def ci_commit_path(commit)
ci_project_ref_commits_path(commit.project, commit.ref, commit.sha) ci_project_ref_commits_path(commit.project, commit.ref, commit.sha)
end end
......
...@@ -12,7 +12,7 @@ module Emails ...@@ -12,7 +12,7 @@ module Emails
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@commit.title} (#{@commit.short_id})")) subject: subject("#{@commit.title} (#{@commit.short_id})"))
SentNotification.record(@commit, recipient_id, reply_key) SentNotification.record_note(@note, recipient_id, reply_key)
end end
def note_issue_email(recipient_id, note_id) def note_issue_email(recipient_id, note_id)
...@@ -27,7 +27,7 @@ module Emails ...@@ -27,7 +27,7 @@ module Emails
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
SentNotification.record(@issue, recipient_id, reply_key) SentNotification.record_note(@note, recipient_id, reply_key)
end end
def note_merge_request_email(recipient_id, note_id) def note_merge_request_email(recipient_id, note_id)
...@@ -43,7 +43,7 @@ module Emails ...@@ -43,7 +43,7 @@ module Emails
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
SentNotification.record(@merge_request, recipient_id, reply_key) SentNotification.record_note(@note, recipient_id, reply_key)
end end
end end
end end
...@@ -428,7 +428,7 @@ class Project < ActiveRecord::Base ...@@ -428,7 +428,7 @@ class Project < ActiveRecord::Base
end end
def gitlab_ci? def gitlab_ci?
gitlab_ci_service && gitlab_ci_service.active gitlab_ci_service && gitlab_ci_service.active && gitlab_ci_project.present?
end end
def ci_services def ci_services
......
...@@ -26,7 +26,7 @@ class DroneCiService < CiService ...@@ -26,7 +26,7 @@ class DroneCiService < CiService
format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated? format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated?
validates :token, validates :token,
presence: true, presence: true,
format: { with: /\A([A-Za-z0-9]+)\z/ }, if: :activated? if: :activated?
after_save :compose_service_hook, if: :activated? after_save :compose_service_hook, if: :activated?
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
# noteable_type :string(255) # noteable_type :string(255)
# recipient_id :integer # recipient_id :integer
# commit_id :string(255) # commit_id :string(255)
# line_code :string(255)
# reply_key :string(255) not null # reply_key :string(255) not null
# #
...@@ -21,13 +22,14 @@ class SentNotification < ActiveRecord::Base ...@@ -21,13 +22,14 @@ class SentNotification < ActiveRecord::Base
validates :noteable_id, presence: true, unless: :for_commit? validates :noteable_id, presence: true, unless: :for_commit?
validates :commit_id, presence: true, if: :for_commit? validates :commit_id, presence: true, if: :for_commit?
validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true
class << self class << self
def for(reply_key) def for(reply_key)
find_by(reply_key: reply_key) find_by(reply_key: reply_key)
end end
def record(noteable, recipient_id, reply_key) def record(noteable, recipient_id, reply_key, params = {})
return unless reply_key return unless reply_key
noteable_id = nil noteable_id = nil
...@@ -38,7 +40,7 @@ class SentNotification < ActiveRecord::Base ...@@ -38,7 +40,7 @@ class SentNotification < ActiveRecord::Base
noteable_id = noteable.id noteable_id = noteable.id
end end
create( params.reverse_merge!(
project: noteable.project, project: noteable.project,
noteable_type: noteable.class.name, noteable_type: noteable.class.name,
noteable_id: noteable_id, noteable_id: noteable_id,
...@@ -46,6 +48,14 @@ class SentNotification < ActiveRecord::Base ...@@ -46,6 +48,14 @@ class SentNotification < ActiveRecord::Base
recipient_id: recipient_id, recipient_id: recipient_id,
reply_key: reply_key reply_key: reply_key
) )
create(params)
end
def record_note(note, recipient_id, reply_key, params = {})
params[:line_code] = note.line_code
record(note.noteable, recipient_id, reply_key, params)
end end
end end
......
- if build.commit && build.project - if build.commit && build.project
%tr.build.alert{class: build_status_alert_class(build)} %tr.build
%td.build-link %td.build-link
= link_to ci_project_build_url(build.project, build) do = link_to ci_project_build_url(build.project, build) do
%strong #{build.id} %strong #{build.id}
%td.status %td.status
= build.status = ci_status_with_icon(build.status)
%td.commit-link %td.commit-link
= commit_link(build.commit) = commit_link(build.commit)
......
- last_commit = project.last_commit - last_commit = project.last_commit
%tr.alert{class: commit_status_alert_class(last_commit) } %tr
%td %td
= project.id = project.id
%td %td
...@@ -7,8 +7,9 @@ ...@@ -7,8 +7,9 @@
%strong= project.name %strong= project.name
%td %td
- if last_commit - if last_commit
#{last_commit.status} (#{commit_link(last_commit)}) = ci_status_with_icon(last_commit.status)
- if project.last_commit_date - if project.last_commit_date
&middot;
= time_ago_in_words project.last_commit_date = time_ago_in_words project.last_commit_date
ago ago
- else - else
......
...@@ -102,9 +102,9 @@ ...@@ -102,9 +102,9 @@
%th Finished at %th Finished at
- @builds.each do |build| - @builds.each do |build|
%tr.build.alert{class: build_status_alert_class(build)} %tr.build
%td.status %td.status
= build.status = ci_status_with_icon(build.status)
%td.status %td.status
= build.project.name = build.project.name
......
%tr.build.alert{class: build_status_alert_class(build)} %tr.build
%td.status %td.status
= build.status = ci_status_with_icon(build.status)
%td.build-link %td.build-link
= link_to ci_project_build_path(build.project, build) do = link_to ci_project_build_path(build.project, build) do
......
#up-build-trace #up-build-trace
- if @commit.matrix? - if @commit.matrix?
%ul.nav.nav-tabs.append-bottom-10 %ul.center-top-menu
- @commit.builds_without_retry_sorted.each do |build| - @commit.builds_without_retry_sorted.each do |build|
%li{class: ('active' if build == @build) } %li{class: ('active' if build == @build) }
= link_to ci_project_build_url(@project, build) do = link_to ci_project_build_url(@project, build) do
%i{class: build_icon_css_class(build)} = ci_icon_for_status(build.status)
%span %span
Build ##{build.id}
- if build.name - if build.name
&middot;
= build.name = build.name
- else
= build.id
- unless @commit.builds_without_retry.include?(@build) - unless @commit.builds_without_retry.include?(@build)
%li.active %li.active
...@@ -19,34 +20,33 @@ ...@@ -19,34 +20,33 @@
%i.fa.fa-warning-sign %i.fa.fa-warning-sign
This build was retried. This build was retried.
.row .gray-content-block
.col-md-9 .build-head
.build-head.alert{class: build_status_alert_class(@build)} %h4
%h4 - if @build.commit.tag?
- if @build.commit.tag? Build for tag
Build for tag %code #{@build.ref}
%code #{@build.ref} - else
- else Build for commit
Build for commit %strong.monospace= commit_link(@build.commit)
%code #{@build.short_sha} from
from
= link_to ci_project_path(@build.project, ref: @build.ref) do
%span.label.label-primary= "#{@build.ref}"
- if @build.duration
.pull-right
%span
%i.fa.fa-time
#{duration_in_words(@build.finished_at, @build.started_at)}
.clearfix = link_to ci_project_path(@build.project, ref: @build.ref) do
= @build.status %strong.monospace= "#{@build.ref}"
.pull-right
= @build.updated_at.stamp('19:00 Aug 27')
- if @build.duration
.pull-right
%span
%i.fa.fa-time
#{duration_in_words(@build.finished_at, @build.started_at)}
.clearfix
= ci_status_with_icon(@build.status)
.pull-right
= @build.updated_at.stamp('19:00 Aug 27')
.row.prepend-top-default
.col-md-9
.clearfix .clearfix
- if @build.active? - if @build.active?
.autoscroll-container .autoscroll-container
...@@ -150,13 +150,16 @@ ...@@ -150,13 +150,16 @@
%h4.title #{pluralize(@builds.count, "other build")} for #{@build.short_sha}: %h4.title #{pluralize(@builds.count, "other build")} for #{@build.short_sha}:
%table.builds %table.builds
- @builds.each_with_index do |build, i| - @builds.each_with_index do |build, i|
%tr.build.alert{class: build_status_alert_class(build)} %tr.build
%td %td
= link_to ci_project_build_url(@project, build) do = ci_icon_for_status(build.status)
%span ##{build.id}
%td %td
- if build.name = link_to ci_project_build_url(@project, build) do
= build.name - if build.name
= build.name
- else
%span ##{build.id}
%td.status= build.status %td.status= build.status
......
%tr.build.alert{class: commit_status_alert_class(commit)} %tr.build
%td.status %td.status
= commit.status = ci_status_with_icon(commit.status)
- if commit.running? - if commit.running?
&middot; &middot;
= commit.stage = commit.stage
......
.commit-info .commit-info
%pre.commit-message .append-bottom-20
#{@commit.git_commit_message} = ci_status_with_icon(@commit.status)
.row .gray-content-block.middle-block
.col-sm-6 %pre.commit-message
- if @commit.compare? #{@commit.git_commit_message}
%p
%span.attr-name Compare: .gray-content-block.second-block
#{gitlab_compare_link(@project, @commit.short_before_sha, @commit.short_sha)} .row
- else .col-sm-6
%p - if @commit.compare?
%span.attr-name Commit: %p
#{gitlab_commit_link(@project, @commit.sha)} %span.attr-name Compare:
#{gitlab_compare_link(@project, @commit.short_before_sha, @commit.short_sha)}
- else
%p
%span.attr-name Commit:
#{gitlab_commit_link(@project, @commit.sha)}
%p
%span.attr-name Branch:
#{gitlab_ref_link(@project, @commit.ref)}
.col-sm-6
%p
%span.attr-name Author:
#{@commit.git_author_name} (#{@commit.git_author_email})
- if @commit.created_at
%p %p
%span.attr-name Created at: %span.attr-name Branch:
#{@commit.created_at.to_s(:short)} #{gitlab_ref_link(@project, @commit.ref)}
.col-sm-6
%p
%span.attr-name Author:
#{@commit.git_author_name} (#{@commit.git_author_email})
- if @commit.created_at
%p
%span.attr-name Created at:
#{@commit.created_at.to_s(:short)}
- if current_user && can?(current_user, :manage_builds, gl_project) - if current_user && can?(current_user, :manage_builds, gl_project)
.pull-right .pull-right
...@@ -42,12 +47,6 @@ ...@@ -42,12 +47,6 @@
.bs-callout.bs-callout-warning .bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit \.gitlab-ci.yml not found in this commit
%h3 Status
.build.alert{class: commit_status_alert_class(@commit)}
.status
= @commit.status.titleize
%h3 %h3
Builds Builds
- if @commit.duration > 0 - if @commit.duration > 0
......
- if project.gitlab_ci_project - if project.gitlab_ci_project
- ci_project = project.gitlab_ci_project - ci_project = project.gitlab_ci_project
- last_commit = ci_project.last_commit - last_commit = ci_project.last_commit
%tr.alert{class: commit_status_alert_class(last_commit) } %tr
%td %td
= link_to [:ci, ci_project] do = link_to [:ci, ci_project] do
= ci_project.name = ci_project.name
%td %td
- if last_commit - if last_commit
#{last_commit.status} (#{commit_link(last_commit)}) = ci_status_with_icon(last_commit.status)
= commit_link(last_commit)
&middot;
- if ci_project.last_commit_date - if ci_project.last_commit_date
= time_ago_in_words ci_project.last_commit_date = time_ago_in_words ci_project.last_commit_date
ago ago
...@@ -33,4 +35,3 @@ ...@@ -33,4 +35,3 @@
= form_tag ci_projects_path do = form_tag ci_projects_path do
= hidden_field_tag :project, project.to_json(methods: [:name_with_namespace, :path_with_namespace, :ssh_url_to_repo]) = hidden_field_tag :project, project.to_json(methods: [:name_with_namespace, :path_with_namespace, :ssh_url_to_repo])
= submit_tag 'Add project to CI', class: 'btn btn-default btn-sm' = submit_tag 'Add project to CI', class: 'btn btn-default btn-sm'
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
-# paginator: the paginator that renders the pagination tags inside -# paginator: the paginator that renders the pagination tags inside
= paginator.render do = paginator.render do
%div.gl-pagination %div.gl-pagination
%ul.pagination %ul.pagination.clearfix
= prev_page_tag unless current_page.first? = prev_page_tag unless current_page.first?
- each_page do |page| - each_page do |page|
- if page.left_outer? || page.right_outer? || page.inside_window? - if page.left_outer? || page.right_outer? || page.inside_window?
......
...@@ -96,7 +96,7 @@ production: &base ...@@ -96,7 +96,7 @@ production: &base
## Reply by email ## Reply by email
# Allow users to comment on issues and merge requests by replying to notification emails. # Allow users to comment on issues and merge requests by replying to notification emails.
# For documentation on how to set this up, see http://doc.gitlab.com/ce/reply_by_email/README.md # For documentation on how to set this up, see http://doc.gitlab.com/ce/reply_by_email/README.html
reply_by_email: reply_by_email:
enabled: false enabled: false
address: "replies+%{reply_key}@gitlab.example.com" address: "replies+%{reply_key}@gitlab.example.com"
......
...@@ -19,7 +19,7 @@ admin = User.create( ...@@ -19,7 +19,7 @@ admin = User.create(
admin.projects_limit = 10000 admin.projects_limit = 10000
admin.admin = true admin.admin = true
admin.save! admin.save!
admin.confirm! admin.confirm
if admin.valid? if admin.valid?
puts %Q[ puts %Q[
......
class DeduplicateUserIdentities < ActiveRecord::Migration class DeduplicateUserIdentities < ActiveRecord::Migration
def change def change
execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;' execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;'
execute 'CREATE TEMPORARY TABLE tt_migration_DeduplicateUserIdentities AS SELECT id,provider,user_id FROM identities;' execute 'CREATE TABLE tt_migration_DeduplicateUserIdentities AS SELECT id,provider,user_id FROM identities;'
execute 'DELETE FROM identities WHERE id NOT IN ( SELECT MIN(id) FROM tt_migration_DeduplicateUserIdentities GROUP BY user_id, provider);' execute 'DELETE FROM identities WHERE id NOT IN ( SELECT MIN(id) FROM tt_migration_DeduplicateUserIdentities GROUP BY user_id, provider);'
execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;' execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;'
end end
......
class AddConsumedTimestepToUsers < ActiveRecord::Migration
def change
add_column :users, :consumed_timestep, :integer
end
end
class AddLineCodeToSentNotification < ActiveRecord::Migration
def change
add_column :sent_notifications, :line_code, :string
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150918084513) do ActiveRecord::Schema.define(version: 20150920161119) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -623,6 +623,7 @@ ActiveRecord::Schema.define(version: 20150918084513) do ...@@ -623,6 +623,7 @@ ActiveRecord::Schema.define(version: 20150918084513) do
t.integer "recipient_id" t.integer "recipient_id"
t.string "commit_id" t.string "commit_id"
t.string "reply_key", null: false t.string "reply_key", null: false
t.string "line_code"
end end
add_index "sent_notifications", ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree add_index "sent_notifications", ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree
...@@ -749,6 +750,7 @@ ActiveRecord::Schema.define(version: 20150918084513) do ...@@ -749,6 +750,7 @@ ActiveRecord::Schema.define(version: 20150918084513) do
t.string "public_email", default: "", null: false t.string "public_email", default: "", null: false
t.integer "dashboard", default: 0 t.integer "dashboard", default: 0
t.integer "project_view", default: 0 t.integer "project_view", default: 0
t.integer "consumed_timestep"
end end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
...@@ -36,7 +36,7 @@ We do not recommend using MySQL due to various issues. For example, case [(in)se ...@@ -36,7 +36,7 @@ We do not recommend using MySQL due to various issues. For example, case [(in)se
mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`; mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
# Grant the GitLab user necessary permissions on the database # Grant the GitLab user necessary permissions on the database
mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, LOCK TABLES ON `gitlabhq_production`.* TO 'git'@'localhost'; mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON `gitlabhq_production`.* TO 'git'@'localhost';
# Quit the database session # Quit the database session
mysql> \q mysql> \q
......
...@@ -10,7 +10,7 @@ See the documentation below for details on how to configure these services. ...@@ -10,7 +10,7 @@ See the documentation below for details on how to configure these services.
- [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider - [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider
- [Slack](slack.md) Integrate with the Slack chat service - [Slack](slack.md) Integrate with the Slack chat service
- [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [OAuth2 provider](oauth_provider.md) OAuth2 application creation
- [Gmail](gitlab_buttons_in_gmail.md) Adds GitLab actions to messages - [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages
GitLab Enterprise Edition contains [advanced JIRA support](http://doc.gitlab.com/ee/integration/jira.html) and [advanced Jenkins support](http://doc.gitlab.com/ee/integration/jenkins.html). GitLab Enterprise Edition contains [advanced JIRA support](http://doc.gitlab.com/ee/integration/jira.html) and [advanced Jenkins support](http://doc.gitlab.com/ee/integration/jenkins.html).
......
# Gmail actions buttons for GitLab
GitLab supports [Google actions in email](https://developers.google.com/gmail/markup/actions/actions-overview).
If correctly setup, emails that require an action will be marked in Gmail.
![gmail_actions_button.png](gmail_actions_button.png)
To get this functioning, you need to be registered with Google.
[See how to register with Google in this document.](https://developers.google.com/gmail/markup/registering-with-google)
*This process has a lot of steps so make sure that you fulfill all requirements set by Google.*
*Your application will be rejected by Google if you fail to do so.*
Pay close attention to:
* Email account used by GitLab to send notification emails needs to have "Consistent history of sending a high volume of mail from your domain (order of hundred emails a day minimum to Gmail) for a few weeks at least".
* "A very very low rate of spam complaints from users."
* Emails must be authenticated via DKIM or SPF
* Before sending the final form("Gmail Schema Whitelist Request"), you must send a real email from your production server. This means that you will have to find a way to send this email from the email address you are registering. You can do this by, for example, forwarding the real email from the email address you are registering or going into the rails console on the GitLab server and triggering the email sending from there.
You can check how it looks going through all the steps laid out in the "Registering with Google" doc in [this GitLab.com issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/1517).
...@@ -98,7 +98,8 @@ module Gitlab ...@@ -98,7 +98,8 @@ module Gitlab
note: reply, note: reply,
noteable_type: sent_notification.noteable_type, noteable_type: sent_notification.noteable_type,
noteable_id: sent_notification.noteable_id, noteable_id: sent_notification.noteable_id,
commit_id: sent_notification.commit_id commit_id: sent_notification.commit_id,
line_code: sent_notification.line_code
).execute ).execute
end end
end end
......
...@@ -37,7 +37,7 @@ describe Profiles::TwoFactorAuthsController do ...@@ -37,7 +37,7 @@ describe Profiles::TwoFactorAuthsController do
context 'with valid pin' do context 'with valid pin' do
before do before do
expect(user).to receive(:valid_otp?).with(pin).and_return(true) expect(user).to receive(:validate_and_consume_otp!).with(pin).and_return(true)
end end
it 'sets two_factor_enabled' do it 'sets two_factor_enabled' do
...@@ -63,7 +63,7 @@ describe Profiles::TwoFactorAuthsController do ...@@ -63,7 +63,7 @@ describe Profiles::TwoFactorAuthsController do
context 'with invalid pin' do context 'with invalid pin' do
before do before do
expect(user).to receive(:valid_otp?).with(pin).and_return(false) expect(user).to receive(:validate_and_consume_otp!).with(pin).and_return(false)
end end
it 'assigns error' do it 'assigns error' do
......
...@@ -712,7 +712,7 @@ describe Notify do ...@@ -712,7 +712,7 @@ describe Notify do
before do before do
user.update_attribute(:email, "user@company.com") user.update_attribute(:email, "user@company.com")
user.confirm! user.confirm
end end
it "is sent from the committer email" do it "is sent from the committer email" do
...@@ -730,7 +730,7 @@ describe Notify do ...@@ -730,7 +730,7 @@ describe Notify do
before do before do
user.update_attribute(:email, "user@something.company.com") user.update_attribute(:email, "user@something.company.com")
user.confirm! user.confirm
end end
it "is sent from the default email" do it "is sent from the default email" do
...@@ -748,7 +748,7 @@ describe Notify do ...@@ -748,7 +748,7 @@ describe Notify do
before do before do
user.update_attribute(:email, "user@mpany.com") user.update_attribute(:email, "user@mpany.com")
user.confirm! user.confirm
end end
it "is sent from the default email" do it "is sent from the default email" do
......
...@@ -34,8 +34,6 @@ describe DroneCiService do ...@@ -34,8 +34,6 @@ describe DroneCiService do
it { is_expected.to validate_presence_of(:drone_url) } it { is_expected.to validate_presence_of(:drone_url) }
it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) } it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) }
it { is_expected.to allow_value('http://ci.example.com').for(:drone_url) } it { is_expected.to allow_value('http://ci.example.com').for(:drone_url) }
it { is_expected.not_to allow_value('token with spaces').for(:token) }
it { is_expected.not_to allow_value('token/with%spaces').for(:token) }
it { is_expected.not_to allow_value('this is not url').for(:drone_url) } it { is_expected.not_to allow_value('this is not url').for(:drone_url) }
it { is_expected.not_to allow_value('http//noturl').for(:drone_url) } it { is_expected.not_to allow_value('http//noturl').for(:drone_url) }
it { is_expected.not_to allow_value('ftp://ci.example.com').for(:drone_url) } it { is_expected.not_to allow_value('ftp://ci.example.com').for(:drone_url) }
...@@ -48,7 +46,6 @@ describe DroneCiService do ...@@ -48,7 +46,6 @@ describe DroneCiService do
it { is_expected.not_to validate_presence_of(:drone_url) } it { is_expected.not_to validate_presence_of(:drone_url) }
it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) } it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) }
it { is_expected.to allow_value('http://drone.example.com').for(:drone_url) } it { is_expected.to allow_value('http://drone.example.com').for(:drone_url) }
it { is_expected.to allow_value('token with spaces').for(:token) }
it { is_expected.to allow_value('ftp://drone.example.com').for(:drone_url) } it { is_expected.to allow_value('ftp://drone.example.com').for(:drone_url) }
end end
end end
......
...@@ -188,7 +188,7 @@ describe User do ...@@ -188,7 +188,7 @@ describe User do
end end
it 'confirms a user' do it 'confirms a user' do
user.confirm! user.confirm
expect(user.confirmed?).to be_truthy expect(user.confirmed?).to be_truthy
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment