Commit 7b327b68 authored by Valery Sizov's avatar Valery Sizov

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

parents d6744ea8 e6149a7e
...@@ -888,7 +888,7 @@ Lint/RequireParentheses: ...@@ -888,7 +888,7 @@ Lint/RequireParentheses:
Lint/RescueException: Lint/RescueException:
Description: 'Avoid rescuing the Exception class.' Description: 'Avoid rescuing the Exception class.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues'
Enabled: false Enabled: true
Lint/ShadowingOuterLocalVariable: Lint/ShadowingOuterLocalVariable:
Description: >- Description: >-
......
...@@ -2,6 +2,17 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -2,6 +2,17 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.3.0 (unreleased) v 8.3.0 (unreleased)
- Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera) - Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera)
- Fix 500 error when update group member permission
- Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera)
- Add ignore whitespace change option to commit view
- Fire update hook from GitLab
v 8.2.2
- Fix 404 in redirection after removing a project (Stan Hu)
- Ensure cached application settings are refreshed at startup (Stan Hu)
- Fix Error 500 when viewing user's personal projects from admin page (Stan Hu)
- Fix: Raw private snippets access workflow
- Prevent "413 Request entity too large" errors when pushing large files with LFS
v 8.2.1 v 8.2.1
- Forcefully update builds that didn't want to update with state machine - Forcefully update builds that didn't want to update with state machine
...@@ -22,7 +33,6 @@ v 8.2.0 ...@@ -22,7 +33,6 @@ v 8.2.0
- Expose build artifacts path as config option - Expose build artifacts path as config option
- Fix grouping of contributors by email in graph. - Fix grouping of contributors by email in graph.
- Improved performance of finding issues with/without labels - Improved performance of finding issues with/without labels
- Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu)
- Fix Drone CI service template not saving properly (Stan Hu) - Fix Drone CI service template not saving properly (Stan Hu)
- Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu) - Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu)
- Added a GitLab specific profiling tool called "Sherlock" (see GitLab CE merge request #1749) - Added a GitLab specific profiling tool called "Sherlock" (see GitLab CE merge request #1749)
......
...@@ -47,10 +47,10 @@ Please send a merge request with a tested solution or a merge request with a fai ...@@ -47,10 +47,10 @@ Please send a merge request with a tested solution or a merge request with a fai
1. **Observed behavior** 1. **Observed behavior**
1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise. 1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise.
1. **Output of checks** 1. **Output of checks**
* Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`); we will only investigate if the tests are passing * Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (For installations with omnibus-gitlab package: `sudo gitlab-rake gitlab:check SANITIZE=true`); For installations from source: `sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`); we will only investigate if the tests are passing
* Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md) * Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md)
* Add the last commit SHA-1 of the GitLab version you used to replicate the issue (obtainable from the help page) * Add the last commit SHA-1 of the GitLab version you used to replicate the issue (obtainable from the help page)
* Describe your setup (use relevant parts from `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`) * Describe your setup (use relevant parts from the env info: For installations with omnibus-gitlab package: `sudo gitlab-rake gitlab:env:info`; For installations from source: `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
1. **Possible fixes**: If you can, link to the line of code that might be responsible for the problem 1. **Possible fixes**: If you can, link to the line of code that might be responsible for the problem
## Merge requests ## Merge requests
......
source "https://rubygems.org" source "https://rubygems.org"
gem 'rails', '4.1.14' gem 'rails', '4.2.4'
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Responders respond_to and respond_with
gem 'responders', '~> 2.0'
# Specify a sprockets version due to security issue # Specify a sprockets version due to security issue
# See https://groups.google.com/forum/#!topic/rubyonrails-security/doAVp0YaTqY # See https://groups.google.com/forum/#!topic/rubyonrails-security/doAVp0YaTqY
...@@ -16,7 +20,7 @@ gem "pg", '~> 0.18.2', group: :postgres ...@@ -16,7 +20,7 @@ gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries # Authentication libraries
gem 'devise', '~> 3.5.2' gem 'devise', '~> 3.5.2'
gem 'devise-async', '~> 0.9.0' gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.1.3' gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.2.2' gem 'omniauth', '~> 1.2.2'
gem 'omniauth-bitbucket', '~> 0.0.2' gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-facebook', '~> 3.0.0' gem 'omniauth-facebook', '~> 3.0.0'
...@@ -29,7 +33,7 @@ gem 'omniauth-shibboleth', '~> 1.2.0' ...@@ -29,7 +33,7 @@ gem 'omniauth-shibboleth', '~> 1.2.0'
gem 'omniauth-twitter', '~> 1.2.0' gem 'omniauth-twitter', '~> 1.2.0'
gem 'omniauth_crowd' gem 'omniauth_crowd'
gem 'gssapi', group: :kerberos gem 'gssapi', group: :kerberos
gem 'rack-oauth2', '~> 1.0.5' gem 'rack-oauth2', '~> 1.2.1'
# Two-factor authentication # Two-factor authentication
gem 'devise-two-factor', '~> 2.0.0' gem 'devise-two-factor', '~> 2.0.0'
...@@ -97,9 +101,10 @@ gem 'redcarpet', '~> 3.3.3' ...@@ -97,9 +101,10 @@ gem 'redcarpet', '~> 3.3.3'
gem 'RedCloth', '~> 4.2.9' gem 'RedCloth', '~> 4.2.9'
gem 'rdoc', '~>3.6' gem 'rdoc', '~>3.6'
gem 'org-ruby', '~> 0.9.12' gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~>0.3.6' gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1' gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.2' gem 'asciidoctor', '~> 1.5.2'
gem 'net-ssh', '~> 3.0.1'
# Diffs # Diffs
gem 'diffy', '~> 3.0.3' gem 'diffy', '~> 3.0.3'
...@@ -128,7 +133,7 @@ gem "httparty", '~> 0.13.3' ...@@ -128,7 +133,7 @@ gem "httparty", '~> 0.13.3'
# Colored output to console # Colored output to console
gem "colored", '~> 1.2' gem "colored", '~> 1.2'
gem "colorize", '~> 0.5.8' gem "colorize", '~> 0.7.0'
# GitLab settings # GitLab settings
gem 'settingslogic', '~> 2.0.9' gem 'settingslogic', '~> 2.0.9'
...@@ -156,7 +161,7 @@ gem "gemnasium-gitlab-service", "~> 0.2" ...@@ -156,7 +161,7 @@ gem "gemnasium-gitlab-service", "~> 0.2"
gem "slack-notifier", "~> 1.2.0" gem "slack-notifier", "~> 1.2.0"
# Asana integration # Asana integration
gem 'asana', '~> 0.0.6' gem 'asana', '~> 0.4.0'
# FogBugz integration # FogBugz integration
gem 'ruby-fogbugz', '~> 0.2.1' gem 'ruby-fogbugz', '~> 0.2.1'
...@@ -189,13 +194,13 @@ gem "sass-rails", '~> 4.0.5' ...@@ -189,13 +194,13 @@ gem "sass-rails", '~> 4.0.5'
gem "coffee-rails", '~> 4.1.0' gem "coffee-rails", '~> 4.1.0'
gem "uglifier", '~> 2.7.2' gem "uglifier", '~> 2.7.2'
gem 'turbolinks', '~> 2.5.0' gem 'turbolinks', '~> 2.5.0'
gem 'jquery-turbolinks', '~> 2.0.1' gem 'jquery-turbolinks', '~> 2.1.0'
gem 'addressable', '~> 2.3.8' gem 'addressable', '~> 2.3.8'
gem 'bootstrap-sass', '~> 3.0' gem 'bootstrap-sass', '~> 3.0'
gem 'font-awesome-rails', '~> 4.2' gem 'font-awesome-rails', '~> 4.2'
gem 'gitlab_emoji', '~> 0.1' gem 'gitlab_emoji', '~> 0.1'
gem 'gon', '~> 5.0.0' 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', '~> 3.1.3'
gem 'jquery-scrollto-rails', '~> 1.4.3' gem 'jquery-scrollto-rails', '~> 1.4.3'
...@@ -218,6 +223,7 @@ group :development do ...@@ -218,6 +223,7 @@ group :development do
gem 'rerun', '~> 0.10.0' gem 'rerun', '~> 0.10.0'
gem 'bullet', require: false gem 'bullet', require: false
gem 'rblineprof', platform: :mri, require: false gem 'rblineprof', platform: :mri, require: false
gem 'web-console', '~> 2.0'
# Better errors handler # Better errors handler
gem 'better_errors', '~> 1.0.1' gem 'better_errors', '~> 1.0.1'
...@@ -274,7 +280,7 @@ group :test do ...@@ -274,7 +280,7 @@ group :test do
gem 'shoulda-matchers', '~> 2.8.0', require: false gem 'shoulda-matchers', '~> 2.8.0', require: false
gem 'email_spec', '~> 1.6.0' gem 'email_spec', '~> 1.6.0'
gem 'webmock', '~> 1.21.0' gem 'webmock', '~> 1.21.0'
gem 'test_after_commit', '~> 0.2.2' gem 'test_after_commit', '~> 0.4.2'
gem 'sham_rack' gem 'sham_rack'
end end
......
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
CFPropertyList (2.3.1) CFPropertyList (2.3.2)
RedCloth (4.2.9) RedCloth (4.2.9)
ace-rails-ap (2.0.1) ace-rails-ap (2.0.1)
actionmailer (4.1.14) actionmailer (4.2.4)
actionpack (= 4.1.14) actionpack (= 4.2.4)
actionview (= 4.1.14) actionview (= 4.2.4)
activejob (= 4.2.4)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
actionpack (4.1.14) rails-dom-testing (~> 1.0, >= 1.0.5)
actionview (= 4.1.14) actionpack (4.2.4)
activesupport (= 4.1.14) actionview (= 4.2.4)
rack (~> 1.5.2) activesupport (= 4.2.4)
rack (~> 1.6)
rack-test (~> 0.6.2) rack-test (~> 0.6.2)
actionview (4.1.14) rails-dom-testing (~> 1.0, >= 1.0.5)
activesupport (= 4.1.14) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.4)
activesupport (= 4.2.4)
builder (~> 3.1) builder (~> 3.1)
erubis (~> 2.7.0) erubis (~> 2.7.0)
activemodel (4.1.14) rails-dom-testing (~> 1.0, >= 1.0.5)
activesupport (= 4.1.14) rails-html-sanitizer (~> 1.0, >= 1.0.2)
activejob (4.2.4)
activesupport (= 4.2.4)
globalid (>= 0.3.0)
activemodel (4.2.4)
activesupport (= 4.2.4)
builder (~> 3.1) builder (~> 3.1)
activerecord (4.1.14) activerecord (4.2.4)
activemodel (= 4.1.14) activemodel (= 4.2.4)
activesupport (= 4.1.14) activesupport (= 4.2.4)
arel (~> 5.0.0) arel (~> 6.0)
activerecord-deprecated_finders (1.0.4) activerecord-deprecated_finders (1.0.4)
activerecord-session_store (0.1.1) activerecord-session_store (0.1.2)
actionpack (>= 4.0.0, < 5) actionpack (>= 4.0.0, < 5)
activerecord (>= 4.0.0, < 5) activerecord (>= 4.0.0, < 5)
railties (>= 4.0.0, < 5) railties (>= 4.0.0, < 5)
activeresource (4.0.0) activesupport (4.2.4)
activemodel (~> 4.0) i18n (~> 0.7)
activesupport (~> 4.0)
rails-observers (~> 0.1.1)
activesupport (4.1.14)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7) json (~> 1.7, >= 1.7.7)
minitest (~> 5.1) minitest (~> 5.1)
thread_safe (~> 0.1) thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1) tzinfo (~> 1.1)
acts-as-taggable-on (3.5.0) acts-as-taggable-on (3.5.0)
activerecord (>= 3.2, < 5) activerecord (>= 3.2, < 5)
addressable (2.3.8) addressable (2.3.8)
after_commit_queue (1.1.0) after_commit_queue (1.3.0)
rails (>= 3.0) activerecord (>= 3.0)
annotate (2.6.10) annotate (2.6.10)
activerecord (>= 3.2, <= 4.3) activerecord (>= 3.2, <= 4.3)
rake (~> 10.4) rake (~> 10.4)
arel (5.0.1.20140414130214) arel (6.0.3)
asana (0.0.6) asana (0.4.0)
activeresource (>= 3.2.3) faraday (~> 0.9)
asciidoctor (1.5.2) faraday_middleware (~> 0.9)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
asciidoctor (1.5.3)
ast (2.1.0) ast (2.1.0)
astrolabe (1.3.1) astrolabe (1.3.1)
parser (~> 2.2) parser (~> 2.2)
attr_encrypted (1.3.4) attr_encrypted (1.3.4)
encryptor (>= 1.3.0) encryptor (>= 1.3.0)
attr_required (1.0.0) attr_required (1.0.0)
autoprefixer-rails (5.2.1.2) autoprefixer-rails (6.1.1)
execjs execjs
json json
awesome_print (1.2.0) awesome_print (1.2.0)
...@@ -85,15 +93,15 @@ GEM ...@@ -85,15 +93,15 @@ GEM
ruby_parser (~> 3.5.0) ruby_parser (~> 3.5.0)
sass (~> 3.0) sass (~> 3.0)
terminal-table (~> 1.4) terminal-table (~> 1.4)
browser (1.0.0) browser (1.0.1)
builder (3.2.2) builder (3.2.2)
bullet (4.14.9) bullet (4.14.10)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.9.0) uniform_notifier (~> 1.9.0)
bundler-audit (0.4.0) bundler-audit (0.4.0)
bundler (~> 1.2) bundler (~> 1.2)
thor (~> 0.18) thor (~> 0.18)
byebug (6.0.2) byebug (8.2.0)
cal-heatmap-rails (0.0.1) cal-heatmap-rails (0.0.1)
capybara (2.4.4) capybara (2.4.4)
mime-types (>= 1.16) mime-types (>= 1.16)
...@@ -108,10 +116,25 @@ GEM ...@@ -108,10 +116,25 @@ GEM
activemodel (>= 3.2.0) activemodel (>= 3.2.0)
activesupport (>= 3.2.0) activesupport (>= 3.2.0)
json (>= 1.7) json (>= 1.7)
celluloid (0.16.0) celluloid (0.17.2)
timers (~> 4.0.0) celluloid-essentials
celluloid-extras
celluloid-fsm
celluloid-pool
celluloid-supervision
timers (>= 4.1.1)
celluloid-essentials (0.20.5)
timers (>= 4.1.1)
celluloid-extras (0.20.5)
timers (>= 4.1.1)
celluloid-fsm (0.20.5)
timers (>= 4.1.1)
celluloid-pool (0.20.5)
timers (>= 4.1.1)
celluloid-supervision (0.20.5)
timers (>= 4.1.1)
charlock_holmes (0.7.3) charlock_holmes (0.7.3)
chunky_png (1.3.4) chunky_png (1.3.5)
cliver (0.3.2) cliver (0.3.2)
coderay (1.1.0) coderay (1.1.0)
coercible (1.0.0) coercible (1.0.0)
...@@ -122,19 +145,19 @@ GEM ...@@ -122,19 +145,19 @@ GEM
coffee-script (2.4.1) coffee-script (2.4.1)
coffee-script-source coffee-script-source
execjs execjs
coffee-script-source (1.9.1.1) coffee-script-source (1.10.0)
colored (1.2) colorize (0.7.7)
colorize (0.5.8)
connection_pool (2.2.0) connection_pool (2.2.0)
coveralls (0.8.2) coveralls (0.8.9)
json (~> 1.8) json (~> 1.8)
rest-client (>= 1.6.8, < 2) rest-client (>= 1.6.8, < 2)
simplecov (~> 0.10.0) simplecov (~> 0.10.0)
term-ansicolor (~> 1.3) term-ansicolor (~> 1.3)
thor (~> 0.19.1) thor (~> 0.19.1)
tins (~> 1.6.0)
crack (0.4.2) crack (0.4.2)
safe_yaml (~> 1.0.0) safe_yaml (~> 1.0.0)
creole (0.3.8) creole (0.5.0)
d3_rails (3.5.6) d3_rails (3.5.6)
railties (>= 3.1.0) railties (>= 3.1.0)
daemons (1.2.3) daemons (1.2.3)
...@@ -154,7 +177,7 @@ GEM ...@@ -154,7 +177,7 @@ GEM
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 (2.0.0) devise-two-factor (2.0.1)
activesupport activesupport
attr_encrypted (~> 1.3.2) attr_encrypted (~> 1.3.2)
devise (~> 3.5.0) devise (~> 3.5.0)
...@@ -163,19 +186,17 @@ GEM ...@@ -163,19 +186,17 @@ GEM
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)
domain_name (0.5.24) domain_name (0.5.25)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (2.1.4) doorkeeper (2.2.2)
railties (>= 3.2) railties (>= 3.2)
dropzonejs-rails (0.7.1) dropzonejs-rails (0.7.2)
rails (> 3.1) rails (> 3.1)
email_reply_parser (0.5.8) email_reply_parser (0.5.8)
email_spec (1.6.0) email_spec (1.6.0)
launchy (~> 2.1) launchy (~> 2.1)
mail (~> 2.2) mail (~> 2.2)
encryptor (1.3.0) encryptor (1.3.0)
enumerize (0.7.0)
activesupport (>= 3.2)
equalizer (0.0.11) equalizer (0.0.11)
erubis (2.7.0) erubis (2.7.0)
escape_utils (1.1.0) escape_utils (1.1.0)
...@@ -192,6 +213,9 @@ GEM ...@@ -192,6 +213,9 @@ GEM
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
faraday_middleware (0.10.0) faraday_middleware (0.10.0)
faraday (>= 0.7.4, < 0.10) faraday (>= 0.7.4, < 0.10)
faraday_middleware-multi_json (0.0.6)
faraday_middleware
multi_json
fastercsv (1.5.5) fastercsv (1.5.5)
ffaker (2.0.0) ffaker (2.0.0)
ffi (1.9.10) ffi (1.9.10)
...@@ -203,7 +227,7 @@ GEM ...@@ -203,7 +227,7 @@ GEM
flog (4.3.2) flog (4.3.2)
ruby_parser (~> 3.1, > 3.1.0) ruby_parser (~> 3.1, > 3.1.0)
sexp_processor (~> 4.4) sexp_processor (~> 4.4)
flowdock (0.7.0) flowdock (0.7.1)
httparty (~> 0.7) httparty (~> 0.7)
multi_json multi_json
fog (1.25.0) fog (1.25.0)
...@@ -225,13 +249,10 @@ GEM ...@@ -225,13 +249,10 @@ GEM
fog-core (~> 1.22) fog-core (~> 1.22)
fog-json fog-json
inflecto (~> 0.0.2) inflecto (~> 0.0.2)
fog-core (1.32.1) fog-core (1.35.0)
builder builder
excon (~> 0.45) excon (~> 0.45)
formatador (~> 0.2) formatador (~> 0.2)
mime-types
net-scp (~> 1.1)
net-ssh (>= 2.1.3)
fog-json (1.0.2) fog-json (1.0.2)
fog-core (~> 1.0) fog-core (~> 1.0)
multi_json (~> 1.10) multi_json (~> 1.10)
...@@ -243,10 +264,10 @@ GEM ...@@ -243,10 +264,10 @@ GEM
fog-core (>= 1.21.0) fog-core (>= 1.21.0)
fog-json fog-json
fog-xml (>= 0.0.1) fog-xml (>= 0.0.1)
fog-sakuracloud (1.0.1) fog-sakuracloud (1.4.0)
fog-core fog-core
fog-json fog-json
fog-softlayer (0.4.7) fog-softlayer (1.0.2)
fog-core fog-core
fog-json fog-json
fog-terremark (0.1.0) fog-terremark (0.1.0)
...@@ -261,7 +282,7 @@ GEM ...@@ -261,7 +282,7 @@ GEM
fog-xml (0.1.2) fog-xml (0.1.2)
fog-core fog-core
nokogiri (~> 1.5, >= 1.5.11) nokogiri (~> 1.5, >= 1.5.11)
font-awesome-rails (4.4.0.0) font-awesome-rails (4.5.0.0)
railties (>= 3.2, < 5.0) railties (>= 3.2, < 5.0)
foreman (0.78.0) foreman (0.78.0)
thor (~> 0.19.1) thor (~> 0.19.1)
...@@ -271,11 +292,11 @@ GEM ...@@ -271,11 +292,11 @@ GEM
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
gemnasium-gitlab-service (0.2.6) gemnasium-gitlab-service (0.2.6)
rugged (~> 0.21) rugged (~> 0.21)
gemojione (2.0.1) gemojione (2.1.0)
json json
get_process_mem (0.2.0) get_process_mem (0.2.0)
gherkin-ruby (0.3.2) gherkin-ruby (0.3.2)
github-linguist (4.7.0) github-linguist (4.7.2)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.3)
escape_utils (~> 1.1.0) escape_utils (~> 1.1.0)
mime-types (>= 1.19) mime-types (>= 1.19)
...@@ -291,8 +312,8 @@ GEM ...@@ -291,8 +312,8 @@ GEM
mime-types (~> 1.15) mime-types (~> 1.15)
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab-license (0.0.4) gitlab-license (0.0.4)
gitlab_emoji (0.1.1) gitlab_emoji (0.2.0)
gemojione (~> 2.0) gemojione (~> 2.1)
gitlab_git (7.2.20) gitlab_git (7.2.20)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.3)
...@@ -304,6 +325,8 @@ GEM ...@@ -304,6 +325,8 @@ GEM
omniauth (~> 1.0) omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1) pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.3) rubyntlm (~> 0.3)
globalid (0.3.6)
activesupport (>= 4.1.0)
gollum-grit_adapter (1.0.0) gollum-grit_adapter (1.0.0)
gitlab-grit (~> 2.7, >= 2.7.1) gitlab-grit (~> 2.7, >= 2.7.1)
gollum-lib (4.0.3) gollum-lib (4.0.3)
...@@ -313,9 +336,11 @@ GEM ...@@ -313,9 +336,11 @@ GEM
rouge (~> 1.10.1) rouge (~> 1.10.1)
sanitize (~> 2.1.0) sanitize (~> 2.1.0)
stringex (~> 2.5.1) stringex (~> 2.5.1)
gon (5.0.4) gon (6.0.1)
actionpack (>= 2.3.0) actionpack (>= 3.0)
json json
multi_json
request_store (>= 1.0)
grape (0.13.0) grape (0.13.0)
activesupport activesupport
builder builder
...@@ -339,7 +364,7 @@ GEM ...@@ -339,7 +364,7 @@ GEM
haml (>= 4.0.6, < 5.0) haml (>= 4.0.6, < 5.0)
html2haml (>= 1.0.1) html2haml (>= 1.0.1)
railties (>= 4.0.1) railties (>= 4.0.1)
hashie (3.4.2) hashie (3.4.3)
highline (1.6.21) highline (1.6.21)
hike (1.2.3) hike (1.2.3)
hipchat (1.5.2) hipchat (1.5.2)
...@@ -357,40 +382,42 @@ GEM ...@@ -357,40 +382,42 @@ GEM
http-cookie (1.0.2) http-cookie (1.0.2)
domain_name (~> 0.5) domain_name (~> 0.5)
http_parser.rb (0.5.3) http_parser.rb (0.5.3)
httparty (0.13.5) httparty (0.13.7)
json (~> 1.8) json (~> 1.8)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
httpclient (2.6.0.1) httpclient (2.7.0.1)
i18n (0.7.0) i18n (0.7.0)
ice_cube (0.11.1) ice_cube (0.11.1)
ice_nine (0.11.1) ice_nine (0.11.1)
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.3) jquery-rails (3.1.4)
railties (>= 3.0, < 5.0) railties (>= 3.0, < 5.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.0.2) jquery-turbolinks (2.1.0)
railties (>= 3.1.0) railties (>= 3.1.0)
turbolinks turbolinks
jquery-ui-rails (4.2.1) jquery-ui-rails (4.2.1)
railties (>= 3.2.16) railties (>= 3.2.16)
json (1.8.3) json (1.8.3)
jwt (1.5.1) jwt (1.5.2)
kaminari (0.16.3) kaminari (0.16.3)
actionpack (>= 3.0.0) actionpack (>= 3.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
kgio (2.9.3) kgio (2.10.0)
launchy (2.4.3) launchy (2.4.3)
addressable (~> 2.3) addressable (~> 2.3)
letter_opener (1.1.2) letter_opener (1.1.2)
launchy (~> 2.2) launchy (~> 2.2)
listen (2.10.1) listen (2.9.0)
celluloid (~> 0.16.0) celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3) rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9) rb-inotify (>= 0.9)
loofah (2.0.3)
nokogiri (>= 1.5.9)
macaddr (1.7.1) macaddr (1.7.1)
systemu (~> 2.6.2) systemu (~> 2.6.2)
mail (2.6.3) mail (2.6.3)
...@@ -407,16 +434,14 @@ GEM ...@@ -407,16 +434,14 @@ GEM
multipart-post (2.0.0) multipart-post (2.0.0)
mysql2 (0.3.20) mysql2 (0.3.20)
nested_form (0.3.2) nested_form (0.3.2)
net-ldap (0.11) net-ldap (0.12.1)
net-scp (1.2.1) net-ssh (3.0.1)
net-ssh (>= 2.6.5) netrc (0.11.0)
net-ssh (2.9.2)
netrc (0.10.3)
newrelic-grape (2.0.0) newrelic-grape (2.0.0)
grape grape
newrelic_rpm newrelic_rpm
newrelic_rpm (3.9.4.245) newrelic_rpm (3.9.4.245)
nokogiri (1.6.6.2) nokogiri (1.6.6.4)
mini_portile (~> 0.6.0) mini_portile (~> 0.6.0)
nprogress-rails (0.1.6.7) nprogress-rails (0.1.6.7)
oauth (0.4.7) oauth (0.4.7)
...@@ -440,12 +465,15 @@ GEM ...@@ -440,12 +465,15 @@ GEM
omniauth-github (1.1.2) omniauth-github (1.1.2)
omniauth (~> 1.0) omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1) omniauth-oauth2 (~> 1.1)
omniauth-gitlab (1.0.0) omniauth-gitlab (1.0.1)
omniauth (~> 1.0) omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0) omniauth-oauth2 (~> 1.0)
omniauth-google-oauth2 (0.2.6) omniauth-google-oauth2 (0.2.10)
omniauth (> 1.0) addressable (~> 2.3)
omniauth-oauth2 (~> 1.1) jwt (~> 1.0)
multi_json (~> 1.3)
omniauth (>= 1.1.1)
omniauth-oauth2 (~> 1.3.1)
omniauth-kerberos (0.3.0) omniauth-kerberos (0.3.0)
omniauth-multipassword omniauth-multipassword
timfel-krb5-auth (~> 0.8) timfel-krb5-auth (~> 0.8)
...@@ -469,18 +497,18 @@ GEM ...@@ -469,18 +497,18 @@ GEM
activesupport activesupport
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
omniauth (~> 1.0) omniauth (~> 1.0)
opennebula (4.12.1) opennebula (4.14.2)
json json
nokogiri nokogiri
rbvmomi rbvmomi
org-ruby (0.9.12) org-ruby (0.9.12)
rubypants (~> 0.2) rubypants (~> 0.2)
orm_adapter (0.5.0) orm_adapter (0.5.0)
paranoia (2.1.3) paranoia (2.1.4)
activerecord (~> 4.0) activerecord (~> 4.0)
parser (2.2.2.6) parser (2.2.3.0)
ast (>= 1.1, < 3.0) ast (>= 1.1, < 3.0)
pg (0.18.2) pg (0.18.4)
poltergeist (1.6.0) poltergeist (1.6.0)
capybara (~> 2.1) capybara (~> 2.1)
cliver (~> 0.3.1) cliver (~> 0.3.1)
...@@ -488,7 +516,7 @@ GEM ...@@ -488,7 +516,7 @@ GEM
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
posix-spawn (0.3.11) posix-spawn (0.3.11)
powerpack (0.0.9) powerpack (0.0.9)
pry (0.10.1) pry (0.10.3)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
...@@ -497,7 +525,7 @@ GEM ...@@ -497,7 +525,7 @@ GEM
pyu-ruby-sasl (0.0.3.3) pyu-ruby-sasl (0.0.3.3)
quiet_assets (1.0.3) quiet_assets (1.0.3)
railties (>= 3.1, < 5.0) railties (>= 3.1, < 5.0)
rack (1.5.5) rack (1.6.4)
rack-accept (0.4.5) rack-accept (0.4.5)
rack (>= 0.4) rack (>= 0.4)
rack-attack (4.3.0) rack-attack (4.3.0)
...@@ -505,7 +533,7 @@ GEM ...@@ -505,7 +533,7 @@ GEM
rack-cors (0.4.0) rack-cors (0.4.0)
rack-mount (0.8.3) rack-mount (0.8.3)
rack (>= 1.0.0) rack (>= 1.0.0)
rack-oauth2 (1.0.10) rack-oauth2 (1.2.1)
activesupport (>= 2.3) activesupport (>= 2.3)
attr_required (>= 0.0.5) attr_required (>= 0.0.5)
httpclient (>= 2.4) httpclient (>= 2.4)
...@@ -515,28 +543,35 @@ GEM ...@@ -515,28 +543,35 @@ GEM
rack rack
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (4.1.14) rails (4.2.4)
actionmailer (= 4.1.14) actionmailer (= 4.2.4)
actionpack (= 4.1.14) actionpack (= 4.2.4)
actionview (= 4.1.14) actionview (= 4.2.4)
activemodel (= 4.1.14) activejob (= 4.2.4)
activerecord (= 4.1.14) activemodel (= 4.2.4)
activesupport (= 4.1.14) activerecord (= 4.2.4)
activesupport (= 4.2.4)
bundler (>= 1.3.0, < 2.0) bundler (>= 1.3.0, < 2.0)
railties (= 4.1.14) railties (= 4.2.4)
sprockets-rails (~> 2.0) sprockets-rails
rails-observers (0.1.2) rails-deprecated_sanitizer (1.0.3)
activemodel (~> 4.0) activesupport (>= 4.2.0.alpha)
railties (4.1.14) rails-dom-testing (1.0.7)
actionpack (= 4.1.14) activesupport (>= 4.2.0.beta, < 5.0)
activesupport (= 4.1.14) nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.2)
loofah (~> 2.0)
railties (4.2.4)
actionpack (= 4.2.4)
activesupport (= 4.2.4)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.0.0) rainbow (2.0.0)
raindrops (0.15.0) raindrops (0.15.0)
rake (10.4.2) rake (10.4.2)
raphael-rails (2.1.2) raphael-rails (2.1.2)
rb-fsevent (0.9.5) rb-fsevent (0.9.6)
rb-inotify (0.9.5) rb-inotify (0.9.5)
ffi (>= 0.5.0) ffi (>= 0.5.0)
rblineprof (0.3.6) rblineprof (0.3.6)
...@@ -548,13 +583,13 @@ GEM ...@@ -548,13 +583,13 @@ GEM
rdoc (3.12.2) rdoc (3.12.2)
json (~> 1.4) json (~> 1.4)
redcarpet (3.3.3) redcarpet (3.3.3)
redis (3.2.1) redis (3.2.2)
redis-actionpack (4.0.0) redis-actionpack (4.0.1)
actionpack (~> 4) actionpack (~> 4)
redis-rack (~> 1.5.0) redis-rack (~> 1.5.0)
redis-store (~> 1.1.0) redis-store (~> 1.1.0)
redis-activesupport (4.1.1) redis-activesupport (4.1.5)
activesupport (~> 4) activesupport (>= 3, < 5)
redis-store (~> 1.1.0) redis-store (~> 1.1.0)
redis-namespace (1.5.2) redis-namespace (1.5.2)
redis (~> 3.0, >= 3.0.4) redis (~> 3.0, >= 3.0.4)
...@@ -565,13 +600,13 @@ GEM ...@@ -565,13 +600,13 @@ GEM
redis-actionpack (~> 4) redis-actionpack (~> 4)
redis-activesupport (~> 4) redis-activesupport (~> 4)
redis-store (~> 1.1.0) redis-store (~> 1.1.0)
redis-store (1.1.6) redis-store (1.1.7)
redis (>= 2.2) redis (>= 2.2)
request_store (1.2.0) request_store (1.2.1)
rerun (0.10.0) rerun (0.10.0)
listen (~> 2.7, >= 2.7.3) listen (~> 2.7, >= 2.7.3)
responders (1.1.2) responders (2.1.0)
railties (>= 3.2, < 4.2) railties (>= 4.2.0, < 5)
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)
...@@ -716,16 +751,16 @@ GEM ...@@ -716,16 +751,16 @@ GEM
term-ansicolor (1.3.2) term-ansicolor (1.3.2)
tins (~> 1.0) tins (~> 1.0)
terminal-table (1.5.2) terminal-table (1.5.2)
test_after_commit (0.2.7) test_after_commit (0.4.2)
activerecord (>= 3.2) activerecord (>= 3.2)
thin (1.6.3) thin (1.6.4)
daemons (~> 1.0, >= 1.0.9) daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0) eventmachine (~> 1.0, >= 1.0.4)
rack (~> 1.0) rack (~> 1.0)
thor (0.19.1) thor (0.19.1)
thread_safe (0.3.5) thread_safe (0.3.5)
tilt (1.4.1) tilt (1.4.1)
timers (4.0.4) timers (4.1.1)
hitimes hitimes
timfel-krb5-auth (0.8.3) timfel-krb5-auth (0.8.3)
tinder (1.10.1) tinder (1.10.1)
...@@ -758,9 +793,9 @@ GEM ...@@ -758,9 +793,9 @@ GEM
kgio (~> 2.6) kgio (~> 2.6)
rack rack
raindrops (~> 0.7) raindrops (~> 0.7)
unicorn-worker-killer (0.4.3) unicorn-worker-killer (0.4.4)
get_process_mem (~> 0) get_process_mem (~> 0)
unicorn (~> 4) unicorn (>= 4, < 6)
uniform_notifier (1.9.0) uniform_notifier (1.9.0)
uuid (2.3.8) uuid (2.3.8)
macaddr (~> 1.0) macaddr (~> 1.0)
...@@ -772,10 +807,15 @@ GEM ...@@ -772,10 +807,15 @@ GEM
equalizer (~> 0.0, >= 0.0.9) equalizer (~> 0.0, >= 0.0.9)
warden (1.2.3) warden (1.2.3)
rack (>= 1.0) rack (>= 1.0)
web-console (2.2.1)
activemodel (>= 4.0)
binding_of_caller (>= 0.7.2)
railties (>= 4.0)
sprockets-rails (>= 2.0, < 4.0)
webmock (1.21.0) webmock (1.21.0)
addressable (>= 2.3.6) addressable (>= 2.3.6)
crack (>= 0.3.2) crack (>= 0.3.2)
websocket-driver (0.6.2) websocket-driver (0.6.3)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2) websocket-extensions (0.1.2)
wikicloth (0.8.1) wikicloth (0.8.1)
...@@ -797,7 +837,7 @@ DEPENDENCIES ...@@ -797,7 +837,7 @@ DEPENDENCIES
addressable (~> 2.3.8) addressable (~> 2.3.8)
after_commit_queue after_commit_queue
annotate (~> 2.6.0) annotate (~> 2.6.0)
asana (~> 0.0.6) asana (~> 0.4.0)
asciidoctor (~> 1.5.2) asciidoctor (~> 1.5.2)
attr_encrypted (~> 1.3.4) attr_encrypted (~> 1.3.4)
awesome_print (~> 1.2.0) awesome_print (~> 1.2.0)
...@@ -816,10 +856,9 @@ DEPENDENCIES ...@@ -816,10 +856,9 @@ DEPENDENCIES
carrierwave (~> 0.9.0) carrierwave (~> 0.9.0)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.3)
coffee-rails (~> 4.1.0) coffee-rails (~> 4.1.0)
colored (~> 1.2) colorize (~> 0.7.0)
colorize (~> 0.5.8)
coveralls (~> 0.8.2) coveralls (~> 0.8.2)
creole (~> 0.3.6) creole (~> 0.5.0)
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)
...@@ -827,11 +866,10 @@ DEPENDENCIES ...@@ -827,11 +866,10 @@ DEPENDENCIES
devise-async (~> 0.9.0) devise-async (~> 0.9.0)
devise-two-factor (~> 2.0.0) devise-two-factor (~> 2.0.0)
diffy (~> 3.0.3) diffy (~> 3.0.3)
doorkeeper (~> 2.1.3) doorkeeper (~> 2.2.0)
dropzonejs-rails (~> 0.7.1) dropzonejs-rails (~> 0.7.1)
email_reply_parser (~> 0.5.8) email_reply_parser (~> 0.5.8)
email_spec (~> 1.6.0) email_spec (~> 1.6.0)
enumerize (~> 0.7.0)
factory_girl_rails (~> 4.3.0) factory_girl_rails (~> 4.3.0)
ffaker (~> 2.0.0) ffaker (~> 2.0.0)
flay flay
...@@ -850,7 +888,7 @@ DEPENDENCIES ...@@ -850,7 +888,7 @@ DEPENDENCIES
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1) gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.0.2) gollum-lib (~> 4.0.2)
gon (~> 5.0.0) gon (~> 6.0.1)
grape (~> 0.13.0) grape (~> 0.13.0)
grape-entity (~> 0.4.2) grape-entity (~> 0.4.2)
gssapi gssapi
...@@ -861,7 +899,7 @@ DEPENDENCIES ...@@ -861,7 +899,7 @@ DEPENDENCIES
jquery-atwho-rails (~> 1.3.2) jquery-atwho-rails (~> 1.3.2)
jquery-rails (~> 3.1.3) jquery-rails (~> 3.1.3)
jquery-scrollto-rails (~> 1.4.3) jquery-scrollto-rails (~> 1.4.3)
jquery-turbolinks (~> 2.0.1) jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 4.2.1) jquery-ui-rails (~> 4.2.1)
kaminari (~> 0.16.3) kaminari (~> 0.16.3)
letter_opener (~> 1.1.2) letter_opener (~> 1.1.2)
...@@ -871,6 +909,7 @@ DEPENDENCIES ...@@ -871,6 +909,7 @@ DEPENDENCIES
mysql2 (~> 0.3.16) mysql2 (~> 0.3.16)
nested_form (~> 0.3.2) nested_form (~> 0.3.2)
net-ldap net-ldap
net-ssh (~> 3.0.1)
newrelic-grape newrelic-grape
newrelic_rpm (~> 3.9.4.245) newrelic_rpm (~> 3.9.4.245)
nprogress-rails (~> 0.1.6.7) nprogress-rails (~> 0.1.6.7)
...@@ -895,8 +934,9 @@ DEPENDENCIES ...@@ -895,8 +934,9 @@ DEPENDENCIES
quiet_assets (~> 1.0.2) quiet_assets (~> 1.0.2)
rack-attack (~> 4.3.0) rack-attack (~> 4.3.0)
rack-cors (~> 0.4.0) rack-cors (~> 0.4.0)
rack-oauth2 (~> 1.0.5) rack-oauth2 (~> 1.2.1)
rails (= 4.1.14) rails (= 4.2.4)
rails-deprecated_sanitizer (~> 1.0.3)
raphael-rails (~> 2.1.2) raphael-rails (~> 2.1.2)
rblineprof rblineprof
rdoc (~> 3.6) rdoc (~> 3.6)
...@@ -904,6 +944,7 @@ DEPENDENCIES ...@@ -904,6 +944,7 @@ DEPENDENCIES
redis-rails (~> 4.0.0) redis-rails (~> 4.0.0)
request_store (~> 1.2.0) request_store (~> 1.2.0)
rerun (~> 0.10.0) rerun (~> 0.10.0)
responders (~> 2.0)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.3.0) rspec-rails (~> 3.3.0)
rubocop (~> 0.28.0) rubocop (~> 0.28.0)
...@@ -933,7 +974,7 @@ DEPENDENCIES ...@@ -933,7 +974,7 @@ DEPENDENCIES
task_list (~> 1.0.2) task_list (~> 1.0.2)
teaspoon (~> 1.0.0) teaspoon (~> 1.0.0)
teaspoon-jasmine (~> 2.2.0) teaspoon-jasmine (~> 2.2.0)
test_after_commit (~> 0.2.2) test_after_commit (~> 0.4.2)
thin (~> 1.6.1) thin (~> 1.6.1)
tinder (~> 1.10.0) tinder (~> 1.10.0)
turbolinks (~> 2.5.0) turbolinks (~> 2.5.0)
...@@ -944,6 +985,7 @@ DEPENDENCIES ...@@ -944,6 +985,7 @@ DEPENDENCIES
unicorn-worker-killer (~> 0.4.2) unicorn-worker-killer (~> 0.4.2)
version_sorter (~> 2.0.0) version_sorter (~> 2.0.0)
virtus (~> 1.0.1) virtus (~> 1.0.1)
web-console (~> 2.0)
webmock (~> 1.21.0) webmock (~> 1.21.0)
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
......
web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"} web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"}
worker: bundle exec sidekiq -q post_receive -q mailer -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default worker: bundle exec sidekiq -q post_receive -q mailer -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q mailers -q default
# mail_room: bundle exec mail_room -q -c config/mail_room.yml # mail_room: bundle exec mail_room -q -c config/mail_room.yml
#= require clipboard #= require clipboard
$ -> genericSuccess = (e) ->
clipboard = new Clipboard '.js-clipboard-trigger', showTooltip(e.trigger, 'Copied!')
text: (trigger) ->
$target = $(trigger.nextElementSibling || trigger.previousElementSibling) # Clear the selection and blur the trigger so it loses its border
$target.data('clipboard-text') || $target.text().trim() e.clearSelection()
$(e.trigger).blur()
clipboard.on 'success', (e) -> # Safari doesn't support `execCommand`, so instead we inform the user to
$(e.trigger). # copy manually.
tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!'). #
tooltip('show'). # See http://clipboardjs.com/#browser-support
one('mouseleave', -> $(this).tooltip('hide')) genericError = (e) ->
if /Mac/i.test(navigator.userAgent)
key = '&#8984;' # Command
else
key = 'Ctrl'
# Clear the selection and blur the trigger so it loses its border showTooltip(e.trigger, "Press #{key}-C to copy")
e.clearSelection()
$(e.trigger).blur()
# Safari doesn't support `execCommand`, so instead we inform the user to showTooltip = (target, title) ->
# copy manually. $(target).
# tooltip(
# See http://clipboardjs.com/#browser-support container: 'body'
clipboard.on 'error', (e) -> html: 'true'
if /Mac/i.test(navigator.userAgent) placement: 'auto bottom'
title = "Press &#8984;-C to copy" title: title
else trigger: 'manual'
title = "Press Ctrl-C to copy" ).
tooltip('show').
one('mouseleave', -> $(this).tooltip('hide'))
$(e.trigger). $ ->
tooltip(trigger: 'manual', placement: 'auto bottom', html: true, title: title). clipboard = new Clipboard '[data-clipboard-target], [data-clipboard-text]'
tooltip('show'). clipboard.on 'success', genericSuccess
one('mouseleave', -> $(this).tooltip('hide')) clipboard.on 'error', genericError
#= require markdown_preview
class @DropzoneInput class @DropzoneInput
constructor: (form) -> constructor: (form) ->
Dropzone.autoDiscover = false Dropzone.autoDiscover = false
...@@ -11,17 +13,14 @@ class @DropzoneInput ...@@ -11,17 +13,14 @@ class @DropzoneInput
uploadProgress = $("<div class=\"div-dropzone-progress\"></div>") uploadProgress = $("<div class=\"div-dropzone-progress\"></div>")
btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>" btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
project_uploads_path = window.project_uploads_path or null project_uploads_path = window.project_uploads_path or null
markdown_preview_path = window.markdown_preview_path or null
max_file_size = gon.max_file_size or 10 max_file_size = gon.max_file_size or 10
form_textarea = $(form).find("textarea.markdown-area") form_textarea = $(form).find("textarea.markdown-area")
form_textarea.wrap "<div class=\"div-dropzone\"></div>" form_textarea.wrap "<div class=\"div-dropzone\"></div>"
form_textarea.on 'paste', (event) => form_textarea.on 'paste', (event) =>
handlePaste(event) handlePaste(event)
form_textarea.on "input", ->
hideReferencedUsers() $(form).setupMarkdownPreview()
form_textarea.on "blur", ->
renderMarkdown()
form_dropzone = $(form).find('.div-dropzone') form_dropzone = $(form).find('.div-dropzone')
form_dropzone.parent().addClass "div-dropzone-wrapper" form_dropzone.parent().addClass "div-dropzone-wrapper"
...@@ -34,42 +33,6 @@ class @DropzoneInput ...@@ -34,42 +33,6 @@ class @DropzoneInput
"opacity": 0 "opacity": 0
"display": "none" "display": "none"
# Preview button
$(document).off "click", ".js-md-preview-button"
$(document).on "click", ".js-md-preview-button", (e) ->
###
Shows the Markdown preview.
Lets the server render GFM into Html and displays it.
###
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-md-write-button").parent().removeClass "active"
form.find(".js-md-preview-button").parent().addClass "active"
# toggle content
form.find(".md-write-holder").hide()
form.find(".md-preview-holder").show()
renderMarkdown()
# Write button
$(document).off "click", ".js-md-write-button"
$(document).on "click", ".js-md-write-button", (e) ->
###
Shows the Markdown textarea.
###
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-md-write-button").parent().addClass "active"
form.find(".js-md-preview-button").parent().removeClass "active"
# toggle content
form.find(".md-write-holder").show()
form.find(".md-preview-holder").hide()
dropzone = form_dropzone.dropzone( dropzone = form_dropzone.dropzone(
url: project_uploads_path url: project_uploads_path
dictDefaultMessage: "" dictDefaultMessage: ""
...@@ -136,41 +99,6 @@ class @DropzoneInput ...@@ -136,41 +99,6 @@ class @DropzoneInput
child = $(dropzone[0]).children("textarea") child = $(dropzone[0]).children("textarea")
hideReferencedUsers = ->
referencedUsers = form.find(".referenced-users")
referencedUsers.hide()
renderReferencedUsers = (users) ->
referencedUsers = form.find(".referenced-users")
if referencedUsers.length
if users.length >= 10
referencedUsers.show()
referencedUsers.find(".js-referenced-users-count").text users.length
else
referencedUsers.hide()
renderMarkdown = ->
preview = form.find(".js-md-preview")
mdText = form.find(".markdown-area").val()
if mdText.trim().length is 0
preview.text "Nothing to preview."
hideReferencedUsers()
else
preview.text "Loading..."
$.ajax(
type: "POST",
url: markdown_preview_path,
data: {
text: mdText
},
dataType: "json"
).success (data) ->
preview.html data.body
preview.syntaxHighlight()
renderReferencedUsers data.references.users
formatLink = (link) -> formatLink = (link) ->
text = "[#{link.alt}](#{link.url})" text = "[#{link.alt}](#{link.url})"
text = "!#{text}" if link.is_image text = "!#{text}" if link.is_image
......
# MarkdownPreview
#
# Handles toggling the "Write" and "Preview" tab clicks, rendering the preview,
# and showing a warning when more than `x` users are referenced.
#
class @MarkdownPreview
# Minimum number of users referenced before triggering a warning
referenceThreshold: 10
showPreview: (form) ->
preview = form.find('.js-md-preview')
mdText = form.find('textarea.markdown-area').val()
if mdText.trim().length == 0
preview.text('Nothing to preview.')
@hideReferencedUsers(form)
else
preview.text('Loading...')
@renderMarkdown mdText, (response) =>
preview.html(response.body)
preview.syntaxHighlight()
@renderReferencedUsers(response.references.users, form)
renderMarkdown: (text, success) ->
return unless window.markdown_preview_path
$.ajax
type: 'POST'
url: window.markdown_preview_path
data: { text: text }
dataType: 'json'
success: success
hideReferencedUsers: (form) ->
referencedUsers = form.find('.referenced-users')
referencedUsers.hide()
renderReferencedUsers: (users, form) ->
referencedUsers = form.find('.referenced-users')
if referencedUsers.length
if users.length >= @referenceThreshold
referencedUsers.show()
referencedUsers.find('.js-referenced-users-count').text(users.length)
else
referencedUsers.hide()
markdownPreview = new MarkdownPreview()
previewButtonSelector = '.js-md-preview-button'
writeButtonSelector = '.js-md-write-button'
$.fn.setupMarkdownPreview = ->
$form = $(this)
form_textarea = $form.find('textarea.markdown-area')
form_textarea.on 'input', -> markdownPreview.hideReferencedUsers($form)
form_textarea.on 'blur', -> markdownPreview.showPreview($form)
$(document).on 'click', previewButtonSelector, (e) ->
e.preventDefault()
$form = $(this).closest('form')
# toggle tabs
$form.find(writeButtonSelector).parent().removeClass('active')
$form.find(previewButtonSelector).parent().addClass('active')
# toggle content
$form.find('.md-write-holder').hide()
$form.find('.md-preview-holder').show()
markdownPreview.showPreview($form)
$(document).on 'click', writeButtonSelector, (e) ->
e.preventDefault()
$form = $(this).closest('form')
# toggle tabs
$form.find(writeButtonSelector).parent().addClass('active')
$form.find(previewButtonSelector).parent().removeClass('active')
# toggle content
$form.find('.md-write-holder').show()
$form.find('.md-preview-holder').hide()
class @Project class @Project
constructor: -> constructor: ->
# Git clone panel switcher # Git protocol switcher
cloneHolder = $('.git-clone-holder') $('.js-protocol-switch').click ->
if cloneHolder.length return if $(@).hasClass('active')
$('a, button', cloneHolder).click ->
$('a, button', cloneHolder).removeClass 'active' # Toggle 'active' for both buttons
$(@).addClass 'active' $('.js-protocol-switch').toggleClass('active')
$('#project_clone', cloneHolder).val $(@).data 'clone'
$(".clone").text("").append $(@).data 'clone' url = $(@).data('clone')
# Update the input field
$('#project_clone').val(url)
# Update the command line instructions
$('.clone').text(url)
# Ref switcher # Ref switcher
$('.project-refs-select').on 'change', -> $('.project-refs-select').on 'change', ->
...@@ -39,4 +45,4 @@ class @Project ...@@ -39,4 +45,4 @@ class @Project
when 4 then label = ' On Mention ' when 4 then label = ' On Mention '
$('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>") $('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>")
$(@).parents('ul').find('li.active').removeClass 'active' $(@).parents('ul').find('li.active').removeClass 'active'
$(@).parent().addClass 'active' $(@).parent().addClass 'active'
\ No newline at end of file
...@@ -127,3 +127,8 @@ ul.content-list { ...@@ -127,3 +127,8 @@ ul.content-list {
} }
} }
.panel > .content-list {
li {
margin: 0;
}
}
...@@ -32,3 +32,7 @@ ...@@ -32,3 +32,7 @@
} }
} }
} }
.panel > .gl-pagination {
margin: 0;
}
...@@ -256,3 +256,9 @@ textarea.js-gfm-input { ...@@ -256,3 +256,9 @@ textarea.js-gfm-input {
.strikethrough { .strikethrough {
text-decoration: line-through; text-decoration: line-through;
} }
h1, h2, h3, h4 {
small {
color: $gl-gray;
}
}
.new-group-member-holder {
margin-top: 50px;
padding-top: 20px;
}
.member-search-form { .member-search-form {
float: left; float: left;
} }
...@@ -15,4 +10,4 @@ ...@@ -15,4 +10,4 @@
.form-control { .form-control {
height: 42px; height: 42px;
} }
} }
\ No newline at end of file
...@@ -90,7 +90,12 @@ ...@@ -90,7 +90,12 @@
} }
.visibility-level-label { .visibility-level-label {
@extend .btn;
@extend .btn-gray;
color: $gray; color: $gray;
cursor: auto;
i { i {
color: inherit; color: inherit;
} }
...@@ -178,6 +183,11 @@ ...@@ -178,6 +183,11 @@
&:active { &:active {
outline: none; outline: none;
} }
&.btn-clipboard {
padding-left: 15px;
padding-right: 15px;
}
} }
.active { .active {
...@@ -556,4 +566,4 @@ pre.light-well { ...@@ -556,4 +566,4 @@ pre.light-well {
z-index: 100; z-index: 100;
position: relative; position: relative;
} }
} }
\ No newline at end of file
...@@ -10,7 +10,7 @@ class AbuseReportsController < ApplicationController ...@@ -10,7 +10,7 @@ class AbuseReportsController < ApplicationController
if @abuse_report.save if @abuse_report.save
if current_application_settings.admin_notification_email.present? if current_application_settings.admin_notification_email.present?
AbuseReportMailer.delay.notify(@abuse_report.id) AbuseReportMailer.notify(@abuse_report.id).deliver_later
end end
message = "Thank you for your report. A GitLab administrator will look into it shortly." message = "Thank you for your report. A GitLab administrator will look into it shortly."
......
...@@ -67,7 +67,12 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -67,7 +67,12 @@ class Projects::CommitController < Projects::ApplicationController
end end
def define_show_vars def define_show_vars
@diffs = commit.diffs if params[:w].to_i == 1
@diffs = commit.diffs({ ignore_whitespace_change: true })
else
@diffs = commit.diffs
end
@notes_count = commit.notes.count @notes_count = commit.notes.count
@builds = ci_commit.builds if ci_commit @builds = ci_commit.builds if ci_commit
......
...@@ -164,12 +164,10 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -164,12 +164,10 @@ class Projects::IssuesController < Projects::ApplicationController
end end
def issue_params def issue_params
permitted = params.require(:issue).permit( params.require(:issue).permit(
:title, :assignee_id, :position, :description, :title, :assignee_id, :position, :description,
:milestone_id, :state_event, :task_num, label_ids: [] :milestone_id, :state_event, :task_num, label_ids: []
) )
params[:issue][:title].strip! if params[:issue][:title]
permitted
end end
def bulk_update_params def bulk_update_params
......
...@@ -325,13 +325,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -325,13 +325,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def merge_request_params def merge_request_params
permitted = params.require(:merge_request).permit( params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch, :title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id, :approver_ids, :target_project_id, :target_branch, :milestone_id, :approver_ids,
:state_event, :description, :task_num, label_ids: [] :state_event, :description, :task_num, label_ids: []
) )
params[:merge_request][:title].strip! if params[:merge_request][:title]
permitted
end end
# Make sure merge requests created before 8.0 # Make sure merge requests created before 8.0
......
...@@ -124,7 +124,7 @@ class ProjectsController < ApplicationController ...@@ -124,7 +124,7 @@ class ProjectsController < ApplicationController
::Projects::DestroyService.new(@project, current_user, {}).execute ::Projects::DestroyService.new(@project, current_user, {}).execute
flash[:alert] = "Project '#{@project.name}' was deleted." flash[:alert] = "Project '#{@project.name}' was deleted."
redirect_back_or_default(default: dashboard_projects_path, options: {}) redirect_to dashboard_projects_path
rescue Projects::DestroyService::DestroyError => ex rescue Projects::DestroyService::DestroyError => ex
redirect_to edit_project_path(@project), alert: ex.message redirect_to edit_project_path(@project), alert: ex.message
end end
......
...@@ -2,7 +2,7 @@ class SnippetsController < ApplicationController ...@@ -2,7 +2,7 @@ class SnippetsController < ApplicationController
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw] before_action :snippet, only: [:show, :edit, :destroy, :update, :raw]
# Allow read snippet # Allow read snippet
before_action :authorize_read_snippet!, only: [:show] before_action :authorize_read_snippet!, only: [:show, :raw]
# Allow modify snippet # Allow modify snippet
before_action :authorize_update_snippet!, only: [:edit, :update] before_action :authorize_update_snippet!, only: [:edit, :update]
......
...@@ -68,7 +68,7 @@ module ApplicationHelper ...@@ -68,7 +68,7 @@ module ApplicationHelper
end end
end end
def avatar_icon(user_or_email = nil, size = nil) def avatar_icon(user_or_email = nil, size = nil, scale = 2)
if user_or_email.is_a?(User) if user_or_email.is_a?(User)
user = user_or_email user = user_or_email
else else
...@@ -78,12 +78,12 @@ module ApplicationHelper ...@@ -78,12 +78,12 @@ module ApplicationHelper
if user if user
user.avatar_url(size) || default_avatar user.avatar_url(size) || default_avatar
else else
gravatar_icon(user_or_email, size) gravatar_icon(user_or_email, size, scale)
end end
end end
def gravatar_icon(user_email = '', size = nil) def gravatar_icon(user_email = '', size = nil, scale = 2)
GravatarService.new.execute(user_email, size) || GravatarService.new.execute(user_email, size, scale) ||
default_avatar default_avatar
end end
......
module ButtonHelper
# Output a "Copy to Clipboard" button
#
# data - Data attributes passed to `content_tag`
#
# Examples:
#
# # Define the clipboard's text
# clipboard_button(clipboard_text: "Foo")
# # => "<button class='...' data-clipboard-text='Foo'>...</button>"
#
# # Define the target element
# clipboard_button(clipboard_target: "#foo")
# # => "<button class='...' data-clipboard-target='#foo'>...</button>"
#
# See http://clipboardjs.com/#usage
def clipboard_button(data = {})
content_tag :button,
icon('clipboard'),
class: 'btn btn-xs btn-clipboard',
data: data,
type: :button
end
def http_clone_button(project)
klass = 'btn js-protocol-switch'
klass << ' active' if default_clone_protocol == 'http'
klass << ' has_tooltip' if current_user.try(:require_password?)
protocol = gitlab_config.protocol.upcase
content_tag :button, protocol,
class: klass,
data: {
clone: project.http_url_to_repo,
container: 'body',
html: 'true',
title: "Set a password on your account<br>to pull or push via #{protocol}"
},
type: :button
end
def ssh_clone_button(project)
klass = 'btn js-protocol-switch'
klass << ' active' if default_clone_protocol == 'ssh'
klass << ' has_tooltip' if current_user.try(:require_ssh_key?)
content_tag :button, 'SSH',
class: klass,
data: {
clone: project.ssh_url_to_repo,
container: 'body',
html: 'true',
title: 'Add an SSH key to your profile<br>to pull or push via SSH.'
},
type: :button
end
end
module ClipboardHelper
def clipboard_button
content_tag :button,
icon('clipboard'),
class: 'btn btn-xs btn-clipboard js-clipboard-trigger',
type: :button
end
end
...@@ -28,6 +28,8 @@ module EmailsHelper ...@@ -28,6 +28,8 @@ module EmailsHelper
return "View #{action.humanize.singularize}" return "View #{action.humanize.singularize}"
end end
end end
nil
end end
def color_email_diff(diffcontent) def color_email_diff(diffcontent)
......
...@@ -173,8 +173,7 @@ module ProjectsHelper ...@@ -173,8 +173,7 @@ module ProjectsHelper
'unknown' 'unknown'
end end
def default_url_to_repo(project = nil) def default_url_to_repo(project = @project)
project = project || @project
current_user ? project.url_to_repo : project.http_url_to_repo current_user ? project.url_to_repo : project.http_url_to_repo
end end
......
...@@ -8,10 +8,6 @@ class BaseMailer < ActionMailer::Base ...@@ -8,10 +8,6 @@ class BaseMailer < ActionMailer::Base
default from: Proc.new { default_sender_address.format } default from: Proc.new { default_sender_address.format }
default reply_to: Proc.new { default_reply_to_address.format } default reply_to: Proc.new { default_reply_to_address.format }
def self.delay
delay_for(2.seconds)
end
def can? def can?
Ability.abilities.allowed?(current_user, action, subject) Ability.abilities.allowed?(current_user, action, subject)
end end
......
...@@ -74,15 +74,23 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -74,15 +74,23 @@ class ApplicationSetting < ActiveRecord::Base
end end
after_commit do after_commit do
Rails.cache.write('application_setting.last', self) Rails.cache.write(cache_key, self)
end end
def self.current def self.current
Rails.cache.fetch('application_setting.last') do Rails.cache.fetch(cache_key) do
ApplicationSetting.last ApplicationSetting.last
end end
end end
def self.expire
Rails.cache.delete(cache_key)
end
def self.cache_key
'application_setting.last'
end
def self.create_from_defaults def self.create_from_defaults
create( create(
default_projects_limit: Settings.gitlab['default_projects_limit'], default_projects_limit: Settings.gitlab['default_projects_limit'],
......
...@@ -14,11 +14,15 @@ module Ci ...@@ -14,11 +14,15 @@ module Ci
extend Ci::Model extend Ci::Model
after_commit do after_commit do
Rails.cache.write('ci_application_setting.last', self) Rails.cache.write(cache_key, self)
end
def self.expire
Rails.cache.delete(cache_key)
end end
def self.current def self.current
Rails.cache.fetch('ci_application_setting.last') do Rails.cache.fetch(cache_key) do
Ci::ApplicationSetting.last Ci::ApplicationSetting.last
end end
end end
...@@ -29,5 +33,9 @@ module Ci ...@@ -29,5 +33,9 @@ module Ci
add_pusher: Settings.gitlab_ci['add_pusher'], add_pusher: Settings.gitlab_ci['add_pusher'],
) )
end end
def self.cache_key
'ci_application_setting.last'
end
end end
end end
...@@ -8,6 +8,7 @@ module Issuable ...@@ -8,6 +8,7 @@ module Issuable
extend ActiveSupport::Concern extend ActiveSupport::Concern
include Participable include Participable
include Mentionable include Mentionable
include StripAttribute
included do included do
belongs_to :author, class_name: "User" belongs_to :author, class_name: "User"
...@@ -51,6 +52,7 @@ module Issuable ...@@ -51,6 +52,7 @@ module Issuable
attr_mentionable :title, :description attr_mentionable :title, :description
participant :author, :assignee, :notes_with_associations participant :author, :assignee, :notes_with_associations
strip_attributes :title
end end
module ClassMethods module ClassMethods
......
# == Strip Attribute module
#
# Contains functionality to clean attributes before validation
#
# Usage:
#
# class Milestone < ActiveRecord::Base
# strip_attributes :title
# end
#
#
module StripAttribute
extend ActiveSupport::Concern
module ClassMethods
def strip_attributes(*attrs)
strip_attrs.concat(attrs)
end
def strip_attrs
@strip_attrs ||= []
end
end
included do
before_validation :strip_attributes
end
def strip_attributes
self.class.strip_attrs.each do |attr|
self[attr].strip! if self[attr] && self[attr].respond_to?(:strip!)
end
end
end
...@@ -22,6 +22,7 @@ class Milestone < ActiveRecord::Base ...@@ -22,6 +22,7 @@ class Milestone < ActiveRecord::Base
include InternalId include InternalId
include Sortable include Sortable
include StripAttribute
belongs_to :project belongs_to :project
has_many :issues has_many :issues
...@@ -35,6 +36,8 @@ class Milestone < ActiveRecord::Base ...@@ -35,6 +36,8 @@ class Milestone < ActiveRecord::Base
validates :title, presence: true validates :title, presence: true
validates :project, presence: true validates :project, presence: true
strip_attributes :title
state_machine :state, initial: :active do state_machine :state, initial: :active do
event :close do event :close do
transition active: :closed transition active: :closed
......
...@@ -44,7 +44,6 @@ class Project < ActiveRecord::Base ...@@ -44,7 +44,6 @@ class Project < ActiveRecord::Base
include CaseSensitivity include CaseSensitivity
extend Gitlab::ConfigHelper extend Gitlab::ConfigHelper
extend Enumerize
UNKNOWN_IMPORT_URL = 'http://unknown.git' UNKNOWN_IMPORT_URL = 'http://unknown.git'
......
...@@ -64,9 +64,9 @@ module Ci ...@@ -64,9 +64,9 @@ module Ci
build.project_recipients.each do |recipient| build.project_recipients.each do |recipient|
case build.status.to_sym case build.status.to_sym
when :success when :success
mailer.build_success_email(build.id, recipient) mailer.build_success_email(build.id, recipient).deliver_later
when :failed when :failed
mailer.build_fail_email(build.id, recipient) mailer.build_fail_email(build.id, recipient).deliver_later
end end
end end
end end
...@@ -78,7 +78,7 @@ module Ci ...@@ -78,7 +78,7 @@ module Ci
end end
def mailer def mailer
Ci::Notify.delay Ci::Notify
end end
end end
end end
...@@ -55,7 +55,7 @@ class GitlabCiService < CiService ...@@ -55,7 +55,7 @@ class GitlabCiService < CiService
end end
def get_ci_commit(sha, ref) def get_ci_commit(sha, ref)
Ci::Project.find(project.gitlab_ci_project).commits.find_by_sha!(sha) Ci::Project.find(project.gitlab_ci_project.id).commits.find_by_sha!(sha)
end end
def commit_status(sha, ref) def commit_status(sha, ref)
......
...@@ -627,9 +627,13 @@ class Repository ...@@ -627,9 +627,13 @@ class Repository
# Run GitLab pre-receive hook # Run GitLab pre-receive hook
pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', path_to_repo) pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', path_to_repo)
status = pre_receive_hook.trigger(gl_id, oldrev, newrev, ref) pre_receive_hook_status = pre_receive_hook.trigger(gl_id, oldrev, newrev, ref)
if status # Run GitLab update hook
update_hook = Gitlab::Git::Hook.new('update', path_to_repo)
update_hook_status = update_hook.trigger(gl_id, oldrev, newrev, ref)
if pre_receive_hook_status && update_hook_status
if was_empty if was_empty
# Create branch # Create branch
rugged.references.create(ref, newrev) rugged.references.create(ref, newrev)
...@@ -652,7 +656,7 @@ class Repository ...@@ -652,7 +656,7 @@ class Repository
# Remove tmp ref and return error to user # Remove tmp ref and return error to user
rugged.references.delete(tmp_ref) rugged.references.delete(tmp_ref)
raise PreReceiveError.new('Commit was rejected by pre-receive hook') raise PreReceiveError.new('Commit was rejected by git hook')
end end
end end
......
...@@ -17,9 +17,8 @@ class SentNotification < ActiveRecord::Base ...@@ -17,9 +17,8 @@ class SentNotification < ActiveRecord::Base
belongs_to :noteable, polymorphic: true belongs_to :noteable, polymorphic: true
belongs_to :recipient, class_name: "User" belongs_to :recipient, class_name: "User"
validate :project, :recipient, :reply_key, presence: true validates :project, :recipient, :reply_key, presence: true
validate :reply_key, uniqueness: true validates :reply_key, uniqueness: true
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 validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true
......
...@@ -665,11 +665,11 @@ class User < ActiveRecord::Base ...@@ -665,11 +665,11 @@ class User < ActiveRecord::Base
email.start_with?('temp-email-for-oauth') email.start_with?('temp-email-for-oauth')
end end
def avatar_url(size = nil) def avatar_url(size = nil, scale = 2)
if avatar.present? if avatar.present?
[gitlab_config.url, avatar.url].join [gitlab_config.url, avatar.url].join
else else
GravatarService.new.execute(email, size) GravatarService.new.execute(email, size, scale)
end end
end end
......
class GravatarService class GravatarService
include Gitlab::CurrentSettings include Gitlab::CurrentSettings
def execute(email, size = nil) def execute(email, size = nil, scale = 2)
if current_application_settings.gravatar_enabled? && email.present? if current_application_settings.gravatar_enabled? && email.present?
size = 40 if size.nil? || size <= 0 size = 40 if size.nil? || size <= 0
sprintf gravatar_url, sprintf gravatar_url,
hash: Digest::MD5.hexdigest(email.strip.downcase), hash: Digest::MD5.hexdigest(email.strip.downcase),
size: size, size: size * scale,
email: email.strip email: email.strip
end end
end end
......
...@@ -38,7 +38,7 @@ module MergeRequests ...@@ -38,7 +38,7 @@ module MergeRequests
} }
repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options) repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options)
rescue Exception => e rescue StandardError => e
merge_request.update(merge_error: "Something went wrong during merge") merge_request.update(merge_error: "Something went wrong during merge")
Rails.logger.error(e.message) Rails.logger.error(e.message)
return false return false
......
...@@ -13,14 +13,14 @@ class NotificationService ...@@ -13,14 +13,14 @@ class NotificationService
# even if user disabled notifications # even if user disabled notifications
def new_key(key) def new_key(key)
if key.user if key.user
mailer.new_ssh_key_email(key.id) mailer.new_ssh_key_email(key.id).deliver_later
end end
end end
# Always notify user about email added to profile # Always notify user about email added to profile
def new_email(email) def new_email(email)
if email.user if email.user
mailer.new_email_email(email.id) mailer.new_email_email(email.id).deliver_later
end end
end end
...@@ -79,17 +79,27 @@ class NotificationService ...@@ -79,17 +79,27 @@ class NotificationService
end end
def merge_mr(merge_request, current_user) def merge_mr(merge_request, current_user)
close_resource_email(merge_request, merge_request.target_project, current_user, 'merged_merge_request_email') close_resource_email(
merge_request,
merge_request.target_project,
current_user,
'merged_merge_request_email'
)
end end
def reopen_mr(merge_request, current_user) def reopen_mr(merge_request, current_user)
reopen_resource_email(merge_request, merge_request.target_project, current_user, 'merge_request_status_email', 'reopened') reopen_resource_email(
merge_request,
merge_request.target_project,
current_user, 'merge_request_status_email',
'reopened'
)
end end
# Notify new user with email after creation # Notify new user with email after creation
def new_user(user, token = nil) def new_user(user, token = nil)
# Don't email omniauth created users # Don't email omniauth created users
mailer.new_user_email(user.id, token) unless user.identities.any? mailer.new_user_email(user.id, token).deliver_later unless user.identities.any?
end end
# Notify users on new note in system # Notify users on new note in system
...@@ -138,50 +148,59 @@ class NotificationService ...@@ -138,50 +148,59 @@ class NotificationService
# build notify method like 'note_commit_email' # build notify method like 'note_commit_email'
notify_method = "note_#{note.noteable_type.underscore}_email".to_sym notify_method = "note_#{note.noteable_type.underscore}_email".to_sym
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(notify_method, recipient.id, note.id) mailer.send(notify_method, recipient.id, note.id).deliver_later
end end
end end
def invite_project_member(project_member, token) def invite_project_member(project_member, token)
mailer.project_member_invited_email(project_member.id, token) mailer.project_member_invited_email(project_member.id, token).deliver_later
end end
def accept_project_invite(project_member) def accept_project_invite(project_member)
mailer.project_invite_accepted_email(project_member.id) mailer.project_invite_accepted_email(project_member.id).deliver_later
end end
def decline_project_invite(project_member) def decline_project_invite(project_member)
mailer.project_invite_declined_email(project_member.project.id, project_member.invite_email, project_member.access_level, project_member.created_by_id) mailer.project_invite_declined_email(
project_member.project.id,
project_member.invite_email,
project_member.access_level,
project_member.created_by_id
).deliver_later
end end
def new_project_member(project_member) def new_project_member(project_member)
mailer.project_access_granted_email(project_member.id) mailer.project_access_granted_email(project_member.id).deliver_later
end end
def update_project_member(project_member) def update_project_member(project_member)
mailer.project_access_granted_email(project_member.id) mailer.project_access_granted_email(project_member.id).deliver_later
end end
def invite_group_member(group_member, token) def invite_group_member(group_member, token)
mailer.group_member_invited_email(group_member.id, token) mailer.group_member_invited_email(group_member.id, token).deliver_later
end end
def accept_group_invite(group_member) def accept_group_invite(group_member)
mailer.group_invite_accepted_email(group_member.id) mailer.group_invite_accepted_email(group_member.id).deliver_later
end end
def decline_group_invite(group_member) def decline_group_invite(group_member)
mailer.group_invite_declined_email(group_member.group.id, group_member.invite_email, group_member.access_level, group_member.created_by_id) mailer.group_invite_declined_email(
group_member.group.id,
group_member.invite_email,
group_member.access_level,
group_member.created_by_id
).deliver_later
end end
def new_group_member(group_member) def new_group_member(group_member)
mailer.group_access_granted_email(group_member.id) mailer.group_access_granted_email(group_member.id).deliver_later
end end
def update_group_member(group_member) def update_group_member(group_member)
mailer.group_access_granted_email(group_member.id) mailer.group_access_granted_email(group_member.id).deliver_later
end end
def project_was_moved(project, old_path_with_namespace) def project_was_moved(project, old_path_with_namespace)
...@@ -189,7 +208,11 @@ class NotificationService ...@@ -189,7 +208,11 @@ class NotificationService
recipients = reject_muted_users(recipients, project) recipients = reject_muted_users(recipients, project)
recipients.each do |recipient| recipients.each do |recipient|
mailer.project_was_moved_email(project.id, recipient.id, old_path_with_namespace) mailer.project_was_moved_email(
project.id,
recipient.id,
old_path_with_namespace
).deliver_later
end end
end end
...@@ -339,7 +362,7 @@ class NotificationService ...@@ -339,7 +362,7 @@ class NotificationService
recipients = build_recipients(target, project, target.author) recipients = build_recipients(target, project, target.author)
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(method, recipient.id, target.id) mailer.send(method, recipient.id, target.id).deliver_later
end end
end end
...@@ -347,7 +370,7 @@ class NotificationService ...@@ -347,7 +370,7 @@ class NotificationService
recipients = build_recipients(target, project, current_user) recipients = build_recipients(target, project, current_user)
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, current_user.id) mailer.send(method, recipient.id, target.id, current_user.id).deliver_later
end end
end end
...@@ -358,7 +381,13 @@ class NotificationService ...@@ -358,7 +381,13 @@ class NotificationService
recipients = build_recipients(target, project, current_user, [previous_assignee]) recipients = build_recipients(target, project, current_user, [previous_assignee])
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, previous_assignee_id, current_user.id) mailer.send(
method,
recipient.id,
target.id,
previous_assignee_id,
current_user.id
).deliver_later
end end
end end
...@@ -366,7 +395,7 @@ class NotificationService ...@@ -366,7 +395,7 @@ class NotificationService
recipients = build_recipients(target, project, current_user) recipients = build_recipients(target, project, current_user)
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, status, current_user.id) mailer.send(method, recipient.id, target.id, status, current_user.id).deliver_later
end end
end end
...@@ -388,7 +417,7 @@ class NotificationService ...@@ -388,7 +417,7 @@ class NotificationService
end end
def mailer def mailer
Notify.delay Notify
end end
def previous_record(object, attribute) def previous_record(object, attribute)
......
- if local_assigns.has_key?(:contributed_projects) && contributed_projects.present?
.panel.panel-default.contributed-projects
.panel-heading Projects contributed to
= render 'shared/projects/list',
projects: contributed_projects.sort_by(&:star_count).reverse,
projects_limit: 5, stars: true, avatar: false
- if local_assigns.has_key?(:projects) && projects.present?
.panel.panel-default
.panel-heading Personal projects
= render 'shared/projects/list',
projects: projects.sort_by(&:star_count).reverse,
projects_limit: 10, stars: true, avatar: false
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
.row .row
.col-md-6 .col-md-6
- if @personal_projects.present? - if @personal_projects.present?
= render 'users/projects', projects: @personal_projects = render 'admin/users/projects', projects: @personal_projects
- else - else
.nothing-here-block This user has no personal projects. .nothing-here-block This user has no personal projects.
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
= label_tag :tag_list, class: 'control-label' do = label_tag :tag_list, class: 'control-label' do
Tags Tags
.col-sm-10 .col-sm-10
= f.text_field :tag_list, class: 'form-control' = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control'
.help-block You can setup builds to only use runners with specific tags .help-block You can setup builds to only use runners with specific tags
.form-actions .form-actions
= f.submit 'Save', class: 'btn btn-save' = f.submit 'Save', class: 'btn btn-save'
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
= @project.name = @project.name
%p %p
Commit: #{link_to @build.short_sha, namespace_project_commit_path(@build.gl_project.namespace, @build.gl_project, @build.sha)} Commit: #{link_to @build.short_sha, namespace_project_commit_url(@build.gl_project.namespace, @build.gl_project, @build.sha)}
%p %p
Author: #{@build.commit.git_author_name} Author: #{@build.commit.git_author_name}
%p %p
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)} %li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
%span{class: ("list-item-name" if show_controls)} %span{class: ("list-item-name" if show_controls)}
- if member.user - if member.user
= image_tag avatar_icon(user, 16), class: "avatar s16", alt: '' = image_tag avatar_icon(user, 24), class: "avatar s24", alt: ''
%strong %strong
= link_to user.name, user_path(user) = link_to user.name, user_path(user)
%span.cgray= user.username %span.cgray= user.username
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
%label.label.label-danger %label.label.label-danger
%strong Blocked %strong Blocked
- else - else
= image_tag avatar_icon(member.invite_email, 16), class: "avatar s16", alt: '' = image_tag avatar_icon(member.invite_email, 24), class: "avatar s24", alt: ''
%strong %strong
= member.invite_email = member.invite_email
%span.cgray %span.cgray
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
- if should_user_see_group_roles?(current_user, @group) - if should_user_see_group_roles?(current_user, @group)
%span.pull-right %span.pull-right
%strong= member.human_access %strong.member-access-level= member.human_access
- if show_controls - if show_controls
- if can?(current_user, :update_group_member, member) - if can?(current_user, :update_group_member, member)
= button_tag class: "btn-xs btn js-toggle-button", = button_tag class: "btn-xs btn js-toggle-button",
......
- page_title "Members" - page_title "Members"
- header_title group_title(@group, "Members", group_group_members_path(@group)) - header_title group_title(@group, "Members", group_group_members_path(@group))
- if should_user_see_group_roles?(current_user, @group) - @blank_container = true
%p.light
Members of group have access to all group projects.
Read more about permissions
%strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
.clearfix.js-toggle-container
= form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do
.form-group
= search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input', spellcheck: false }
= button_tag 'Search', class: 'btn'
.group-members-page
- if current_user && current_user.can?(:admin_group_member, @group) - if current_user && current_user.can?(:admin_group_member, @group)
<<<<<<< HEAD
.pull-right .pull-right
- if @group.ldap_synced? - if @group.ldap_synced?
= form_tag(reset_access_group_ldap_path(@group), method: :put, class: 'inline') do = form_tag(reset_access_group_ldap_path(@group), method: :put, class: 'inline') do
...@@ -53,6 +44,34 @@ ...@@ -53,6 +44,34 @@
= paginate @members, theme: 'gitlab' = paginate @members, theme: 'gitlab'
= render 'shared/confirm_modal', phrase: 'reset' = render 'shared/confirm_modal', phrase: 'reset'
=======
.panel.panel-default
.panel-heading
Add new user to group
.panel-body
- if should_user_see_group_roles?(current_user, @group)
%p.light
Members of group have access to all group projects.
.new-group-member-holder
= render "new_group_member"
.panel.panel-default
.panel-heading
%strong #{@group.name}
group members
%small
(#{@members.total_count})
.pull-right
= form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do
.form-group
= search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false }
= button_tag class: 'btn', title: 'Search' do
= icon("search")
%ul.content-list
- @members.each do |member|
= render 'groups/group_members/group_member', member: member, show_controls: true
= paginate @members, theme: 'gitlab'
>>>>>>> origin/master
:javascript :javascript
$('form.member-search-form').on('submit', function(event) { $('form.member-search-form').on('submit', function(event) {
......
- empty_repo = @project.empty_repo? - empty_repo = @project.empty_repo?
.project-home-panel.clearfix{:class => ("empty-project" if empty_repo)} .project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)}
.project-identicon-holder .project-identicon-holder
= project_icon(@project, alt: '', class: 'project-avatar avatar s90') = project_icon(@project, alt: '', class: 'project-avatar avatar s90')
.project-home-desc .project-home-desc
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
Forked from Forked from
= link_to project_path(forked_from_project) do = link_to project_path(forked_from_project) do
= forked_from_project.namespace.try(:name) = forked_from_project.namespace.try(:name)
.cover-controls
.visibility-level-label
= visibility_level_icon(@project.visibility_level)
= visibility_level_label(@project.visibility_level)
- if @project.mirror? - if @project.mirror?
- import_url = @project.safe_import_url - import_url = @project.safe_import_url
...@@ -27,7 +31,7 @@ ...@@ -27,7 +31,7 @@
= render 'projects/buttons/fork' = render 'projects/buttons/fork'
= render "shared/clone_panel" = render "shared/clone_panel"
.split-repo-buttons .split-repo-buttons
= render "projects/buttons/update_mirror" = render "projects/buttons/update_mirror"
= render "projects/buttons/download" = render "projects/buttons/download"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%a.js-md-write-button(href="#md-write-holder" tabindex="-1") %a.js-md-write-button(href="#md-write-holder" tabindex="-1")
Write Write
%li %li
%a.js-md-preview-button(href="md-preview-holder" tabindex="-1") %a.js-md-preview-button(href="#md-preview-holder" tabindex="-1")
Preview Preview
- if defined?(referenced_users) && referenced_users - if defined?(referenced_users) && referenced_users
......
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
- if ci_commit - if ci_commit
= render_ci_status(ci_commit) = render_ci_status(ci_commit)
&nbsp; &nbsp;
= clipboard_button = clipboard_button(clipboard_text: commit.id)
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id", data: {clipboard_text: commit.id} = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
.notes_count .notes_count
- if note_count > 0 - if note_count > 0
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
.form-group .form-group
= f.label :tag_list, "Tags", class: 'control-label' = f.label :tag_list, "Tags", class: 'control-label'
.col-sm-10 .col-sm-10
= f.text_field :tag_list, maxlength: 2000, class: "form-control" = f.text_field :tag_list, value: @project.tag_list.to_s, maxlength: 2000, class: "form-control"
%p.help-block Separate tags with commas. %p.help-block Separate tags with commas.
%fieldset.features %fieldset.features
......
...@@ -18,9 +18,9 @@ ...@@ -18,9 +18,9 @@
= link_to_member(@project, participant, name: false, size: 24) = link_to_member(@project, participant, name: false, size: 24)
.col-md-3 .col-md-3
.input-group.cross-project-reference .input-group.cross-project-reference
%span.slead.has_tooltip{title: 'Cross-project reference'} %span#cross-project-reference.slead.has_tooltip{title: 'Cross-project reference'}
= cross_project_reference(@project, @issue) = cross_project_reference(@project, @issue)
= clipboard_button = clipboard_button(clipboard_target: '#cross-project-reference')
.row .row
%section.col-md-9 %section.col-md-9
......
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
= render "projects/merge_requests/show/participants" = render "projects/merge_requests/show/participants"
.col-md-3 .col-md-3
.input-group.cross-project-reference .input-group.cross-project-reference
%span.slead.has_tooltip{title: 'Cross-project reference'} %span#cross-project-reference.slead.has_tooltip{title: 'Cross-project reference'}
= cross_project_reference(@project, @merge_request) = cross_project_reference(@project, @merge_request)
= clipboard_button = clipboard_button(clipboard_target: '#cross-project-reference')
.row .row
%section.col-md-9 %section.col-md-9
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
group members group members
%small %small
(#{members.count}) (#{members.count})
.panel-head-actions .pull-right
= link_to group_group_members_path(@group), class: 'btn btn-sm' do = link_to group_group_members_path(@group), class: 'btn' do
%i.fa.fa-pencil-square-o = icon('pencil-square-o')
Edit group members Edit group members
%ul.well-list %ul.content-list
- members.each do |member| - members.each do |member|
= render 'groups/group_members/group_member', member: member, show_controls: false = render 'groups/group_members/group_member', member: member, show_controls: false
- if members.count > 20 - if members.count > 20
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
%li{class: "#{dom_class(member)} js-toggle-container project_member_row access-#{member.human_access.downcase}", id: dom_id(member)} %li{class: "#{dom_class(member)} js-toggle-container project_member_row access-#{member.human_access.downcase}", id: dom_id(member)}
%span.list-item-name %span.list-item-name
- if member.user - if member.user
= image_tag avatar_icon(user, 16), class: "avatar s16", alt: '' = image_tag avatar_icon(user, 24), class: "avatar s24", alt: ''
%strong %strong
= link_to user.name, user_path(user) = link_to user.name, user_path(user)
%span.cgray= user.username %span.cgray= user.username
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
%label.label.label-danger %label.label.label-danger
%strong Blocked %strong Blocked
- else - else
= image_tag avatar_icon(member.invite_email, 16), class: "avatar s16", alt: '' = image_tag avatar_icon(member.invite_email, 24), class: "avatar s24", alt: ''
%strong %strong
= member.invite_email = member.invite_email
%span.cgray %span.cgray
......
.panel.panel-default.prepend-top-20 .panel.panel-default
.panel-heading .panel-heading
%strong #{@project.name} %strong #{@project.name}
project members project members
%small %small
(#{members.count}) (#{members.count})
%ul.well-list .pull-right
= form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do
.form-group
= search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false }
= button_tag class: 'btn', title: 'Search' do
= icon("search")
%ul.content-list
- members.each do |project_member| - members.each do |project_member|
= render 'project_member', member: project_member = render 'project_member', member: project_member
:javascript
$('form.member-search-form').on('submit', function (event) {
event.preventDefault();
Turbolinks.visit(this.action + '?' + $(this).serialize());
});
- page_title "Members" - page_title "Members"
= render "header_title" = render "header_title"
- @blank_container = true
<<<<<<< HEAD
.gray-content-block.top-block .gray-content-block.top-block
.clearfix.js-toggle-container .clearfix.js-toggle-container
= form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do
...@@ -34,9 +36,22 @@ ...@@ -34,9 +36,22 @@
= render "group_members", members: @group_members = render "group_members", members: @group_members
- if @project_group_links.any? && @project.allowed_to_share_with_group? - if @project_group_links.any? && @project.allowed_to_share_with_group?
= render "shared_group_members" = render "shared_group_members"
=======
.project-members-page
- if can?(current_user, :admin_project_member, @project)
.panel.panel-default
.panel-heading
Add new user to project
.pull-right
= link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "Import members from another project" do
Import members
.panel-body
%p.light
Users with access to this project are listed below.
= render "new_project_member"
= render "team", members: @project_members
>>>>>>> origin/master
:javascript - if @group
$('form.member-search-form').on('submit', function (event) { = render "group_members", members: @group_members
event.preventDefault();
Turbolinks.visit(this.action + '?' + $(this).serialize());
});
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
= label_tag :tag_list, class: 'control-label' do = label_tag :tag_list, class: 'control-label' do
Tags Tags
.col-sm-10 .col-sm-10
= f.text_field :tag_list, class: 'form-control' = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control'
.help-block You can setup jobs to only use runners with specific tags .help-block You can setup jobs to only use runners with specific tags
.form-actions .form-actions
= f.submit 'Save', class: 'btn btn-save' = f.submit 'Save', class: 'btn btn-save'
...@@ -2,25 +2,9 @@ ...@@ -2,25 +2,9 @@
.git-clone-holder.input-group .git-clone-holder.input-group
.input-group-addon.git-protocols .input-group-addon.git-protocols
.input-group-btn .input-group-btn
%button{ | = ssh_clone_button(project)
type: 'button', |
class: "btn #{ 'active' if default_clone_protocol == 'ssh' }#{ ' has_tooltip' if current_user && current_user.require_ssh_key? }", |
:"data-clone" => project.ssh_url_to_repo, |
:"data-title" => "Add an SSH key to your profile<br> to pull or push via SSH.",
:"data-html" => "true",
:"data-container" => "body"}
SSH
.input-group-btn .input-group-btn
%button{ | = http_clone_button(project)
type: 'button', |
class: "btn #{ 'active' if default_clone_protocol == 'http' }#{ ' has_tooltip' if current_user && current_user.require_password? }", |
:"data-clone" => project.http_url_to_repo, |
:"data-title" => "Set a password on your account<br> to pull or push via #{gitlab_config.protocol.upcase}.",
:"data-html" => "true",
:"data-container" => "body"}
= gitlab_config.protocol.upcase
= text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true
- if project.kind_of?(Project) .input-group-btn
.input-group-addon.has_tooltip{title: "#{visibility_level_label(project.visibility_level)} project", data: { container: "body" } } = clipboard_button(clipboard_target: '#project_clone')
.visibility-level-label
= visibility_level_icon(project.visibility_level)
...@@ -25,6 +25,12 @@ ...@@ -25,6 +25,12 @@
%strong %strong
= @transaction.duration.round(2) = @transaction.duration.round(2)
= t('sherlock.seconds') = t('sherlock.seconds')
%li
%span.light
#{t('sherlock.query_time')}
%strong
= @transaction.query_duration.round(2)
= t('sherlock.seconds')
%li %li
%span.light %span.light
#{t('sherlock.finished_at')}: #{t('sherlock.finished_at')}:
......
...@@ -46,6 +46,6 @@ class EmailReceiverWorker ...@@ -46,6 +46,6 @@ class EmailReceiverWorker
return return
end end
EmailRejectionMailer.delay.rejection(reason, raw, can_retry) EmailRejectionMailer.rejection(reason, raw, can_retry).deliver_later
end end
end end
...@@ -53,7 +53,7 @@ class EmailsOnPushWorker ...@@ -53,7 +53,7 @@ class EmailsOnPushWorker
reverse_compare: reverse_compare, reverse_compare: reverse_compare,
send_from_committer_email: send_from_committer_email, send_from_committer_email: send_from_committer_email,
disable_diffs: disable_diffs disable_diffs: disable_diffs
).deliver ).deliver_now
# These are input errors and won't be corrected even if Sidekiq retries # These are input errors and won't be corrected even if Sidekiq retries
rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e
logger.info("Failed to send e-mail for project '#{project.name_with_namespace}' to #{recipient}: #{e}") logger.info("Failed to send e-mail for project '#{project.name_with_namespace}' to #{recipient}: #{e}")
......
File mode changed from 100644 to 100755
#!/usr/bin/env ruby #!/usr/bin/env ruby
begin APP_PATH = File.expand_path('../../config/application', __FILE__)
load File.expand_path("../spring", __FILE__)
rescue LoadError
end
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot' require_relative '../config/boot'
require 'rails/commands' require 'rails/commands'
#!/usr/bin/env ruby #!/usr/bin/env ruby
begin require_relative '../config/boot'
load File.expand_path("../spring", __FILE__) require 'rake'
rescue LoadError Rake.application.run
end
require 'bundler/setup'
load Gem.bin_path('rake', 'rake')
#!/usr/bin/env ruby
require 'pathname'
# path to your application root.
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
Dir.chdir APP_ROOT do
# This script is a starting point to setup your application.
# Add necessary setup steps to this file:
puts "== Installing dependencies =="
system "gem install bundler --conservative"
system "bundle check || bundle install"
# puts "\n== Copying sample files =="
# unless File.exist?("config/database.yml")
# system "cp config/database.yml.sample config/database.yml"
# end
puts "\n== Preparing database =="
system "bin/rake db:setup"
puts "\n== Removing old logs and tempfiles =="
system "rm -f log/*"
system "rm -rf tmp/cache"
puts "\n== Restarting application server =="
system "touch tmp/restart.txt"
end
File mode changed from 100644 to 100755
...@@ -99,6 +99,10 @@ module Gitlab ...@@ -99,6 +99,10 @@ module Gitlab
redis_config_hash[:expires_in] = 2.weeks # Cache should not grow forever redis_config_hash[:expires_in] = 2.weeks # Cache should not grow forever
config.cache_store = :redis_store, redis_config_hash config.cache_store = :redis_store, redis_config_hash
config.active_record.raise_in_transactional_callbacks = true
config.active_job.queue_adapter = :sidekiq
# This is needed for gitlab-shell # This is needed for gitlab-shell
ENV['GITLAB_PATH_OUTSIDE_HOOK'] = ENV['PATH'] ENV['GITLAB_PATH_OUTSIDE_HOOK'] = ENV['PATH']
end end
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
require File.expand_path('../application', __FILE__) require File.expand_path('../application', __FILE__)
# Initialize the rails application # Initialize the rails application
Gitlab::Application.initialize! Rails.application.initialize!
Gitlab::Application.configure do Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb # Settings specified here will take precedence over those in config/application.rb
# In the development environment your application's code is reloaded on # In the development environment your application's code is reloaded on
......
Gitlab::Application.configure do Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb # Settings specified here will take precedence over those in config/application.rb
# Code is not reloaded between requests # Code is not reloaded between requests
...@@ -9,7 +9,7 @@ Gitlab::Application.configure do ...@@ -9,7 +9,7 @@ Gitlab::Application.configure do
config.action_controller.perform_caching = true config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this) # Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false config.serve_static_files = false
# Compress JavaScripts and CSS. # Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier config.assets.js_compressor = :uglifier
......
Gitlab::Application.configure do Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb # Settings specified here will take precedence over those in config/application.rb
# The test environment is used exclusively to run your application's # The test environment is used exclusively to run your application's
...@@ -8,7 +8,7 @@ Gitlab::Application.configure do ...@@ -8,7 +8,7 @@ Gitlab::Application.configure do
config.cache_classes = false config.cache_classes = false
# Configure static asset server for tests with Cache-Control for performance # Configure static asset server for tests with Cache-Control for performance
config.serve_static_assets = true config.serve_static_files = true
config.static_cache_control = "public, max-age=3600" config.static_cache_control = "public, max-age=3600"
# Show full error reports and disable caching # Show full error reports and disable caching
...@@ -32,4 +32,6 @@ Gitlab::Application.configure do ...@@ -32,4 +32,6 @@ Gitlab::Application.configure do
config.eager_load = false config.eager_load = false
config.cache_store = :null_store config.cache_store = :null_store
config.active_job.queue_adapter = :test
end end
...@@ -33,13 +33,15 @@ class Settings < Settingslogic ...@@ -33,13 +33,15 @@ class Settings < Settingslogic
end end
def build_gitlab_shell_ssh_path_prefix def build_gitlab_shell_ssh_path_prefix
user_host = "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}"
if gitlab_shell.ssh_port != 22 if gitlab_shell.ssh_port != 22
"ssh://#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:#{gitlab_shell.ssh_port}/" "ssh://#{user_host}:#{gitlab_shell.ssh_port}/"
else else
if gitlab_shell.ssh_host.include? ':' if gitlab_shell.ssh_host.include? ':'
"[#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}]:" "[#{user_host}]:"
else else
"#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:" "#{user_host}:"
end end
end end
end end
...@@ -332,3 +334,12 @@ if Rails.env.test? ...@@ -332,3 +334,12 @@ if Rails.env.test?
Settings.gitlab['default_can_create_group'] = true Settings.gitlab['default_can_create_group'] = true
Settings.gitlab['default_can_create_team'] = false Settings.gitlab['default_can_create_team'] = false
end end
# Force a refresh of application settings at startup
begin
ApplicationSetting.expire
Ci::ApplicationSetting.expire
rescue
# Gracefully handle when Redis is not available. For example,
# omnibus may fail here during assets:precompile.
end
# Be sure to restart your server when you modify this file. # Be sure to restart your server when you modify this file.
Gitlab::Application.config.action_dispatch.cookies_serializer = :hybrid Rails.application.config.action_dispatch.cookies_serializer = :hybrid
...@@ -8,4 +8,4 @@ unless Gitlab.config.gitlab_on_standard_port? ...@@ -8,4 +8,4 @@ unless Gitlab.config.gitlab_on_standard_port?
default_url_options[:port] = Gitlab.config.gitlab.port default_url_options[:port] = Gitlab.config.gitlab.port
end end
Gitlab::Application.routes.default_url_options = default_url_options Rails.application.routes.default_url_options = default_url_options
...@@ -4,13 +4,13 @@ ...@@ -4,13 +4,13 @@
# If you change this file in a Merge Request, please also create a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests # If you change this file in a Merge Request, please also create a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
paths_to_be_protected = [ paths_to_be_protected = [
"#{Gitlab::Application.config.relative_url_root}/users/password", "#{Rails.application.config.relative_url_root}/users/password",
"#{Gitlab::Application.config.relative_url_root}/users/sign_in", "#{Rails.application.config.relative_url_root}/users/sign_in",
"#{Gitlab::Application.config.relative_url_root}/api/#{API::API.version}/session.json", "#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session.json",
"#{Gitlab::Application.config.relative_url_root}/api/#{API::API.version}/session", "#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session",
"#{Gitlab::Application.config.relative_url_root}/users", "#{Rails.application.config.relative_url_root}/users",
"#{Gitlab::Application.config.relative_url_root}/users/confirmation", "#{Rails.application.config.relative_url_root}/users/confirmation",
"#{Gitlab::Application.config.relative_url_root}/unsubscribes/" "#{Rails.application.config.relative_url_root}/unsubscribes/"
] ]
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# with darker backgrounds. This patch tweaks the colors a bit so the output is # with darker backgrounds. This patch tweaks the colors a bit so the output is
# actually readable. # actually readable.
if Rails.env.development? and RUBY_ENGINE == 'ruby' and ENV['ENABLE_LINEPROF'] if Rails.env.development? and RUBY_ENGINE == 'ruby' and ENV['ENABLE_LINEPROF']
Gitlab::Application.config.middleware.use(Rack::Lineprof) Rails.application.config.middleware.use(Rack::Lineprof)
module Rack module Rack
class Lineprof class Lineprof
......
...@@ -22,15 +22,15 @@ def find_secure_token ...@@ -22,15 +22,15 @@ def find_secure_token
end end
end end
Gitlab::Application.config.secret_token = find_secure_token Rails.application.config.secret_token = find_secure_token
Gitlab::Application.config.secret_key_base = find_secure_token Rails.application.config.secret_key_base = find_secure_token
# CI # CI
def generate_new_secure_token def generate_new_secure_token
SecureRandom.hex(64) SecureRandom.hex(64)
end end
if Gitlab::Application.secrets.db_key_base.blank? if Rails.application.secrets.db_key_base.blank?
warn "Missing `db_key_base` for '#{Rails.env}' environment. The secrets will be generated and stored in `config/secrets.yml`" warn "Missing `db_key_base` for '#{Rails.env}' environment. The secrets will be generated and stored in `config/secrets.yml`"
all_secrets = YAML.load_file('config/secrets.yml') if File.exist?('config/secrets.yml') all_secrets = YAML.load_file('config/secrets.yml') if File.exist?('config/secrets.yml')
...@@ -46,5 +46,5 @@ if Gitlab::Application.secrets.db_key_base.blank? ...@@ -46,5 +46,5 @@ if Gitlab::Application.secrets.db_key_base.blank?
file.write(YAML.dump(all_secrets)) file.write(YAML.dump(all_secrets))
end end
Gitlab::Application.secrets.db_key_base = env_secrets['db_key_base'] Rails.application.secrets.db_key_base = env_secrets['db_key_base']
end end
...@@ -3,20 +3,21 @@ ...@@ -3,20 +3,21 @@
require 'gitlab/current_settings' require 'gitlab/current_settings'
include Gitlab::CurrentSettings include Gitlab::CurrentSettings
# allow it to fail: it may to do so when create_from_defaults is executed before migrations are actually done # allow it to fail: it may do so when create_from_defaults is executed before migrations are actually done
begin begin
Settings.gitlab['session_expire_delay'] = current_application_settings.session_expire_delay Settings.gitlab['session_expire_delay'] = current_application_settings.session_expire_delay || 10080
rescue rescue
Settings.gitlab['session_expire_delay'] ||= 10080
end end
unless Rails.env.test? unless Rails.env.test?
Gitlab::Application.config.session_store( Gitlab::Application.config.session_store(
:redis_store, # Using the cookie_store would enable session replay attacks. :redis_store, # Using the cookie_store would enable session replay attacks.
servers: Gitlab::Application.config.cache_store[1].merge(namespace: 'session:gitlab'), # re-use the Redis config from the Rails cache store servers: Rails.application.config.cache_store[1].merge(namespace: 'session:gitlab'), # re-use the Redis config from the Rails cache store
key: '_gitlab_session', key: '_gitlab_session',
secure: Gitlab.config.gitlab.https, secure: Gitlab.config.gitlab.https,
httponly: true, httponly: true,
expire_after: Settings.gitlab['session_expire_delay'] * 60, expire_after: Settings.gitlab['session_expire_delay'] * 60,
path: (Gitlab::Application.config.relative_url_root.nil?) ? '/' : Gitlab::Application.config.relative_url_root path: (Rails.application.config.relative_url_root.nil?) ? '/' : Gitlab::Application.config.relative_url_root
) )
end end
if Gitlab::Sherlock.enabled? if Gitlab::Sherlock.enabled?
Gitlab::Application.configure do |config| Rails.application.configure do |config|
config.middleware.use(Gitlab::Sherlock::Middleware) config.middleware.use(Gitlab::Sherlock::Middleware)
end end
end end
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# If you change this file in a Merge Request, please also create a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests # If you change this file in a Merge Request, please also create a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
if Rails.env.production? if Rails.env.production?
Gitlab::Application.config.action_mailer.delivery_method = :smtp Rails.application.config.action_mailer.delivery_method = :smtp
ActionMailer::Base.smtp_settings = { ActionMailer::Base.smtp_settings = {
address: "email.server.com", address: "email.server.com",
......
app = Gitlab::Application app = Rails.application
if app.config.serve_static_assets if app.config.serve_static_files
# The `ActionDispatch::Static` middleware intercepts requests for static files # The `ActionDispatch::Static` middleware intercepts requests for static files
# by checking if they exist in the `/public` directory. # by checking if they exist in the `/public` directory.
# We're replacing it with our `Gitlab::Middleware::Static` that does the same, # We're replacing it with our `Gitlab::Middleware::Static` that does the same,
......
...@@ -35,3 +35,4 @@ en: ...@@ -35,3 +35,4 @@ en:
events: Events events: Events
percent: '%' percent: '%'
count: Count count: Count
query_time: Query Time
require 'sidekiq/web' require 'sidekiq/web'
require 'api/api' require 'api/api'
Gitlab::Application.routes.draw do Rails.application.routes.draw do
if Gitlab::Sherlock.enabled? if Gitlab::Sherlock.enabled?
namespace :sherlock do namespace :sherlock do
resources :transactions, only: [:index, :show] do resources :transactions, only: [:index, :show] do
......
...@@ -16,7 +16,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -16,7 +16,7 @@ ActiveRecord::Schema.define(version: 20151118162244) 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"
create_table "abuse_reports", force: true do |t| create_table "abuse_reports", force: :cascade do |t|
t.integer "reporter_id" t.integer "reporter_id"
t.integer "user_id" t.integer "user_id"
t.text "message" t.text "message"
...@@ -24,17 +24,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -24,17 +24,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.datetime "updated_at" t.datetime "updated_at"
end end
create_table "appearances", force: true do |t|
t.string "title"
t.text "description"
t.string "logo"
t.integer "updated_by"
t.datetime "created_at"
t.datetime "updated_at"
t.string "dark_logo"
t.string "light_logo"
end
create_table "application_settings", force: true do |t| create_table "application_settings", force: true do |t|
t.integer "default_projects_limit" t.integer "default_projects_limit"
t.boolean "signup_enabled" t.boolean "signup_enabled"
...@@ -63,24 +52,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -63,24 +52,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.integer "max_artifacts_size", default: 100, null: false t.integer "max_artifacts_size", default: 100, null: false
end end
create_table "approvals", force: true do |t|
t.integer "merge_request_id", null: false
t.integer "user_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "approvers", force: true do |t|
t.integer "target_id", null: false
t.string "target_type"
t.integer "user_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "approvers", ["target_id", "target_type"], name: "index_approvers_on_target_id_and_target_type", using: :btree
add_index "approvers", ["user_id"], name: "index_approvers_on_user_id", using: :btree
create_table "audit_events", force: true do |t| create_table "audit_events", force: true do |t|
t.integer "author_id", null: false t.integer "author_id", null: false
t.string "type", null: false t.string "type", null: false
...@@ -95,7 +66,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -95,7 +66,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "audit_events", ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree add_index "audit_events", ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree
add_index "audit_events", ["type"], name: "index_audit_events_on_type", using: :btree add_index "audit_events", ["type"], name: "index_audit_events_on_type", using: :btree
create_table "broadcast_messages", force: true do |t| create_table "broadcast_messages", force: :cascade do |t|
t.text "message", null: false t.text "message", null: false
t.datetime "starts_at" t.datetime "starts_at"
t.datetime "ends_at" t.datetime "ends_at"
...@@ -106,14 +77,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -106,14 +77,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.string "font" t.string "font"
end end
create_table "ci_application_settings", force: true do |t| create_table "ci_application_settings", force: :cascade do |t|
t.boolean "all_broken_builds" t.boolean "all_broken_builds"
t.boolean "add_pusher" t.boolean "add_pusher"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
end end
create_table "ci_builds", force: true do |t| create_table "ci_builds", force: :cascade do |t|
t.integer "project_id" t.integer "project_id"
t.string "status" t.string "status"
t.datetime "finished_at" t.datetime "finished_at"
...@@ -153,7 +124,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -153,7 +124,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_builds", ["status"], name: "index_ci_builds_on_status", using: :btree add_index "ci_builds", ["status"], name: "index_ci_builds_on_status", using: :btree
add_index "ci_builds", ["type"], name: "index_ci_builds_on_type", using: :btree add_index "ci_builds", ["type"], name: "index_ci_builds_on_type", using: :btree
create_table "ci_commits", force: true do |t| create_table "ci_commits", force: :cascade do |t|
t.integer "project_id" t.integer "project_id"
t.string "ref" t.string "ref"
t.string "sha" t.string "sha"
...@@ -174,7 +145,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -174,7 +145,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_commits", ["project_id"], name: "index_ci_commits_on_project_id", using: :btree add_index "ci_commits", ["project_id"], name: "index_ci_commits_on_project_id", using: :btree
add_index "ci_commits", ["sha"], name: "index_ci_commits_on_sha", using: :btree add_index "ci_commits", ["sha"], name: "index_ci_commits_on_sha", using: :btree
create_table "ci_events", force: true do |t| create_table "ci_events", force: :cascade do |t|
t.integer "project_id" t.integer "project_id"
t.integer "user_id" t.integer "user_id"
t.integer "is_admin" t.integer "is_admin"
...@@ -187,7 +158,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -187,7 +158,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_events", ["is_admin"], name: "index_ci_events_on_is_admin", using: :btree add_index "ci_events", ["is_admin"], name: "index_ci_events_on_is_admin", using: :btree
add_index "ci_events", ["project_id"], name: "index_ci_events_on_project_id", using: :btree add_index "ci_events", ["project_id"], name: "index_ci_events_on_project_id", using: :btree
create_table "ci_jobs", force: true do |t| create_table "ci_jobs", force: :cascade do |t|
t.integer "project_id", null: false t.integer "project_id", null: false
t.text "commands" t.text "commands"
t.boolean "active", default: true, null: false t.boolean "active", default: true, null: false
...@@ -204,7 +175,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -204,7 +175,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_jobs", ["deleted_at"], name: "index_ci_jobs_on_deleted_at", using: :btree add_index "ci_jobs", ["deleted_at"], name: "index_ci_jobs_on_deleted_at", using: :btree
add_index "ci_jobs", ["project_id"], name: "index_ci_jobs_on_project_id", using: :btree add_index "ci_jobs", ["project_id"], name: "index_ci_jobs_on_project_id", using: :btree
create_table "ci_projects", force: true do |t| create_table "ci_projects", force: :cascade do |t|
t.string "name" t.string "name"
t.integer "timeout", default: 3600, null: false t.integer "timeout", default: 3600, null: false
t.datetime "created_at" t.datetime "created_at"
...@@ -230,7 +201,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -230,7 +201,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_projects", ["gitlab_id"], name: "index_ci_projects_on_gitlab_id", using: :btree add_index "ci_projects", ["gitlab_id"], name: "index_ci_projects_on_gitlab_id", using: :btree
add_index "ci_projects", ["shared_runners_enabled"], name: "index_ci_projects_on_shared_runners_enabled", using: :btree add_index "ci_projects", ["shared_runners_enabled"], name: "index_ci_projects_on_shared_runners_enabled", using: :btree
create_table "ci_runner_projects", force: true do |t| create_table "ci_runner_projects", force: :cascade do |t|
t.integer "runner_id", null: false t.integer "runner_id", null: false
t.integer "project_id", null: false t.integer "project_id", null: false
t.datetime "created_at" t.datetime "created_at"
...@@ -240,7 +211,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -240,7 +211,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_runner_projects", ["project_id"], name: "index_ci_runner_projects_on_project_id", using: :btree add_index "ci_runner_projects", ["project_id"], name: "index_ci_runner_projects_on_project_id", using: :btree
add_index "ci_runner_projects", ["runner_id"], name: "index_ci_runner_projects_on_runner_id", using: :btree add_index "ci_runner_projects", ["runner_id"], name: "index_ci_runner_projects_on_runner_id", using: :btree
create_table "ci_runners", force: true do |t| create_table "ci_runners", force: :cascade do |t|
t.string "token" t.string "token"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
...@@ -255,7 +226,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -255,7 +226,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.string "architecture" t.string "architecture"
end end
create_table "ci_services", force: true do |t| create_table "ci_services", force: :cascade do |t|
t.string "type" t.string "type"
t.string "title" t.string "title"
t.integer "project_id", null: false t.integer "project_id", null: false
...@@ -267,7 +238,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -267,7 +238,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_services", ["project_id"], name: "index_ci_services_on_project_id", using: :btree add_index "ci_services", ["project_id"], name: "index_ci_services_on_project_id", using: :btree
create_table "ci_sessions", force: true do |t| create_table "ci_sessions", force: :cascade do |t|
t.string "session_id", null: false t.string "session_id", null: false
t.text "data" t.text "data"
t.datetime "created_at" t.datetime "created_at"
...@@ -277,7 +248,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -277,7 +248,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_sessions", ["session_id"], name: "index_ci_sessions_on_session_id", using: :btree add_index "ci_sessions", ["session_id"], name: "index_ci_sessions_on_session_id", using: :btree
add_index "ci_sessions", ["updated_at"], name: "index_ci_sessions_on_updated_at", using: :btree add_index "ci_sessions", ["updated_at"], name: "index_ci_sessions_on_updated_at", using: :btree
create_table "ci_taggings", force: true do |t| create_table "ci_taggings", force: :cascade do |t|
t.integer "tag_id" t.integer "tag_id"
t.integer "taggable_id" t.integer "taggable_id"
t.string "taggable_type" t.string "taggable_type"
...@@ -290,14 +261,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -290,14 +261,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "ci_taggings_idx", unique: true, using: :btree add_index "ci_taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "ci_taggings_idx", unique: true, using: :btree
add_index "ci_taggings", ["taggable_id", "taggable_type", "context"], name: "index_ci_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree 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: true do |t| create_table "ci_tags", force: :cascade do |t|
t.string "name" t.string "name"
t.integer "taggings_count", default: 0 t.integer "taggings_count", default: 0
end end
add_index "ci_tags", ["name"], name: "index_ci_tags_on_name", unique: true, using: :btree add_index "ci_tags", ["name"], name: "index_ci_tags_on_name", unique: true, using: :btree
create_table "ci_trigger_requests", force: true do |t| create_table "ci_trigger_requests", force: :cascade do |t|
t.integer "trigger_id", null: false t.integer "trigger_id", null: false
t.text "variables" t.text "variables"
t.datetime "created_at" t.datetime "created_at"
...@@ -305,7 +276,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -305,7 +276,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.integer "commit_id" t.integer "commit_id"
end end
create_table "ci_triggers", force: true do |t| create_table "ci_triggers", force: :cascade do |t|
t.string "token" t.string "token"
t.integer "project_id", null: false t.integer "project_id", null: false
t.datetime "deleted_at" t.datetime "deleted_at"
...@@ -315,7 +286,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -315,7 +286,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_triggers", ["deleted_at"], name: "index_ci_triggers_on_deleted_at", using: :btree add_index "ci_triggers", ["deleted_at"], name: "index_ci_triggers_on_deleted_at", using: :btree
create_table "ci_variables", force: true do |t| create_table "ci_variables", force: :cascade do |t|
t.integer "project_id", null: false t.integer "project_id", null: false
t.string "key" t.string "key"
t.text "value" t.text "value"
...@@ -326,14 +297,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -326,14 +297,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "ci_variables", ["project_id"], name: "index_ci_variables_on_project_id", using: :btree add_index "ci_variables", ["project_id"], name: "index_ci_variables_on_project_id", using: :btree
create_table "ci_web_hooks", force: true do |t| create_table "ci_web_hooks", force: :cascade do |t|
t.string "url", null: false t.string "url", null: false
t.integer "project_id", null: false t.integer "project_id", null: false
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
end end
create_table "deploy_keys_projects", force: true do |t| create_table "deploy_keys_projects", force: :cascade do |t|
t.integer "deploy_key_id", null: false t.integer "deploy_key_id", null: false
t.integer "project_id", null: false t.integer "project_id", null: false
t.datetime "created_at" t.datetime "created_at"
...@@ -342,7 +313,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -342,7 +313,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "deploy_keys_projects", ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree add_index "deploy_keys_projects", ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree
create_table "emails", force: true do |t| create_table "emails", force: :cascade do |t|
t.integer "user_id", null: false t.integer "user_id", null: false
t.string "email", null: false t.string "email", null: false
t.datetime "created_at" t.datetime "created_at"
...@@ -352,7 +323,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -352,7 +323,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "emails", ["email"], name: "index_emails_on_email", unique: true, using: :btree add_index "emails", ["email"], name: "index_emails_on_email", unique: true, using: :btree
add_index "emails", ["user_id"], name: "index_emails_on_user_id", using: :btree add_index "emails", ["user_id"], name: "index_emails_on_user_id", using: :btree
create_table "events", force: true do |t| create_table "events", force: :cascade do |t|
t.string "target_type" t.string "target_type"
t.integer "target_id" t.integer "target_id"
t.string "title" t.string "title"
...@@ -371,7 +342,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -371,7 +342,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "events", ["target_id"], name: "index_events_on_target_id", using: :btree add_index "events", ["target_id"], name: "index_events_on_target_id", using: :btree
add_index "events", ["target_type"], name: "index_events_on_target_type", using: :btree add_index "events", ["target_type"], name: "index_events_on_target_type", using: :btree
create_table "forked_project_links", force: true do |t| create_table "forked_project_links", force: :cascade do |t|
t.integer "forked_to_project_id", null: false t.integer "forked_to_project_id", null: false
t.integer "forked_from_project_id", null: false t.integer "forked_from_project_id", null: false
t.datetime "created_at" t.datetime "created_at"
...@@ -380,28 +351,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -380,28 +351,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree 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 "git_hooks", force: true do |t|
t.string "force_push_regex"
t.string "delete_branch_regex"
t.string "commit_message_regex"
t.boolean "deny_delete_tag"
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "author_email_regex"
t.boolean "member_check", default: false, null: false
t.string "file_name_regex"
t.boolean "is_sample", default: false
t.integer "max_file_size", default: 0
end
create_table "historical_data", force: true do |t|
t.date "date", null: false
t.integer "active_user_count"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "identities", force: true do |t| create_table "identities", force: true do |t|
t.string "extern_uid" t.string "extern_uid"
t.string "provider" t.string "provider"
...@@ -413,7 +362,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -413,7 +362,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "identities", ["created_at", "id"], name: "index_identities_on_created_at_and_id", using: :btree add_index "identities", ["created_at", "id"], name: "index_identities_on_created_at_and_id", using: :btree
add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree
create_table "issues", force: true do |t| create_table "issues", force: :cascade do |t|
t.string "title" t.string "title"
t.integer "assignee_id" t.integer "assignee_id"
t.integer "author_id" t.integer "author_id"
...@@ -439,7 +388,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -439,7 +388,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "issues", ["state"], name: "index_issues_on_state", using: :btree add_index "issues", ["state"], name: "index_issues_on_state", using: :btree
add_index "issues", ["title"], name: "index_issues_on_title", using: :btree add_index "issues", ["title"], name: "index_issues_on_title", using: :btree
create_table "keys", force: true do |t| create_table "keys", force: :cascade do |t|
t.integer "user_id" t.integer "user_id"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
...@@ -453,7 +402,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -453,7 +402,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "keys", ["created_at", "id"], name: "index_keys_on_created_at_and_id", using: :btree add_index "keys", ["created_at", "id"], name: "index_keys_on_created_at_and_id", using: :btree
add_index "keys", ["user_id"], name: "index_keys_on_user_id", using: :btree add_index "keys", ["user_id"], name: "index_keys_on_user_id", using: :btree
create_table "label_links", force: true do |t| create_table "label_links", force: :cascade do |t|
t.integer "label_id" t.integer "label_id"
t.integer "target_id" t.integer "target_id"
t.string "target_type" t.string "target_type"
...@@ -464,7 +413,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -464,7 +413,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "label_links", ["label_id"], name: "index_label_links_on_label_id", using: :btree add_index "label_links", ["label_id"], name: "index_label_links_on_label_id", using: :btree
add_index "label_links", ["target_id", "target_type"], name: "index_label_links_on_target_id_and_target_type", using: :btree add_index "label_links", ["target_id", "target_type"], name: "index_label_links_on_target_id_and_target_type", using: :btree
create_table "labels", force: true do |t| create_table "labels", force: :cascade do |t|
t.string "title" t.string "title"
t.string "color" t.string "color"
t.integer "project_id" t.integer "project_id"
...@@ -475,15 +424,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -475,15 +424,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree
create_table "ldap_group_links", force: true do |t|
t.string "cn", null: false
t.integer "group_access", null: false
t.integer "group_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "provider"
end
create_table "lfs_objects", force: true do |t| create_table "lfs_objects", force: true do |t|
t.string "oid", null: false t.string "oid", null: false
t.integer "size", null: false t.integer "size", null: false
...@@ -494,7 +434,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -494,7 +434,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree
create_table "lfs_objects_projects", force: true do |t| create_table "lfs_objects_projects", force: :cascade do |t|
t.integer "lfs_object_id", null: false t.integer "lfs_object_id", null: false
t.integer "project_id", null: false t.integer "project_id", null: false
t.datetime "created_at" t.datetime "created_at"
...@@ -503,12 +443,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -503,12 +443,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "lfs_objects_projects", ["project_id"], name: "index_lfs_objects_projects_on_project_id", using: :btree add_index "lfs_objects_projects", ["project_id"], name: "index_lfs_objects_projects_on_project_id", using: :btree
create_table "licenses", force: true do |t|
t.text "data", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "members", force: true do |t| create_table "members", force: true do |t|
t.integer "access_level", null: false t.integer "access_level", null: false
t.integer "source_id", null: false t.integer "source_id", null: false
...@@ -531,7 +465,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -531,7 +465,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "members", ["type"], name: "index_members_on_type", using: :btree add_index "members", ["type"], name: "index_members_on_type", using: :btree
add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree
create_table "merge_request_diffs", force: true do |t| create_table "merge_request_diffs", force: :cascade do |t|
t.string "state" t.string "state"
t.text "st_commits" t.text "st_commits"
t.text "st_diffs" t.text "st_diffs"
...@@ -542,7 +476,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -542,7 +476,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "merge_request_diffs", ["merge_request_id"], name: "index_merge_request_diffs_on_merge_request_id", unique: true, using: :btree 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: true do |t| create_table "merge_requests", force: :cascade do |t|
t.string "target_branch", null: false t.string "target_branch", null: false
t.string "source_branch", null: false t.string "source_branch", null: false
t.integer "source_project_id", null: false t.integer "source_project_id", null: false
...@@ -574,7 +508,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -574,7 +508,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "merge_requests", ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree add_index "merge_requests", ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree
add_index "merge_requests", ["title"], name: "index_merge_requests_on_title", using: :btree add_index "merge_requests", ["title"], name: "index_merge_requests_on_title", using: :btree
create_table "milestones", force: true do |t| create_table "milestones", force: :cascade do |t|
t.string "title", null: false t.string "title", null: false
t.integer "project_id", null: false t.integer "project_id", null: false
t.text "description" t.text "description"
...@@ -591,8 +525,8 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -591,8 +525,8 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree
create_table "namespaces", force: true do |t| create_table "namespaces", force: true do |t|
t.string "name", null: false t.string "name", null: false
t.string "path", null: false t.string "path", null: false
t.integer "owner_id" t.integer "owner_id"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
...@@ -611,7 +545,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -611,7 +545,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "namespaces", ["public"], name: "index_namespaces_on_public", using: :btree add_index "namespaces", ["public"], name: "index_namespaces_on_public", using: :btree
add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree
create_table "notes", force: true do |t| create_table "notes", force: :cascade do |t|
t.text "note" t.text "note"
t.string "noteable_type" t.string "noteable_type"
t.integer "author_id" t.integer "author_id"
...@@ -640,7 +574,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -640,7 +574,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree
add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree
create_table "oauth_access_grants", force: true do |t| create_table "oauth_access_grants", force: :cascade do |t|
t.integer "resource_owner_id", null: false t.integer "resource_owner_id", null: false
t.integer "application_id", null: false t.integer "application_id", null: false
t.string "token", null: false t.string "token", null: false
...@@ -653,7 +587,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -653,7 +587,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree
create_table "oauth_access_tokens", force: true do |t| create_table "oauth_access_tokens", force: :cascade do |t|
t.integer "resource_owner_id" t.integer "resource_owner_id"
t.integer "application_id" t.integer "application_id"
t.string "token", null: false t.string "token", null: false
...@@ -668,7 +602,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -668,7 +602,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id", using: :btree add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id", using: :btree
add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree
create_table "oauth_applications", force: true do |t| create_table "oauth_applications", force: :cascade do |t|
t.string "name", null: false t.string "name", null: false
t.string "uid", null: false t.string "uid", null: false
t.string "secret", null: false t.string "secret", null: false
...@@ -683,20 +617,12 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -683,20 +617,12 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree
add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree
create_table "project_group_links", force: true do |t|
t.integer "project_id", null: false
t.integer "group_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "group_access", default: 30, null: false
end
create_table "project_import_data", force: true do |t| create_table "project_import_data", force: true do |t|
t.integer "project_id" t.integer "project_id"
t.text "data" t.text "data"
end end
create_table "projects", force: true do |t| create_table "projects", force: :cascade do |t|
t.string "name" t.string "name"
t.string "path" t.string "path"
t.text "description" t.text "description"
...@@ -743,7 +669,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -743,7 +669,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "projects", ["star_count"], name: "index_projects_on_star_count", using: :btree add_index "projects", ["star_count"], name: "index_projects_on_star_count", using: :btree
add_index "projects", ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree add_index "projects", ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree
create_table "protected_branches", force: true do |t| create_table "protected_branches", force: :cascade do |t|
t.integer "project_id", null: false t.integer "project_id", null: false
t.string "name", null: false t.string "name", null: false
t.datetime "created_at" t.datetime "created_at"
...@@ -753,7 +679,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -753,7 +679,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
create_table "releases", force: true do |t| create_table "releases", force: :cascade do |t|
t.string "tag" t.string "tag"
t.text "description" t.text "description"
t.integer "project_id" t.integer "project_id"
...@@ -764,7 +690,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -764,7 +690,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "releases", ["project_id", "tag"], name: "index_releases_on_project_id_and_tag", using: :btree add_index "releases", ["project_id", "tag"], name: "index_releases_on_project_id_and_tag", using: :btree
add_index "releases", ["project_id"], name: "index_releases_on_project_id", using: :btree add_index "releases", ["project_id"], name: "index_releases_on_project_id", using: :btree
create_table "sent_notifications", force: true do |t| create_table "sent_notifications", force: :cascade do |t|
t.integer "project_id" t.integer "project_id"
t.integer "noteable_id" t.integer "noteable_id"
t.string "noteable_type" t.string "noteable_type"
...@@ -776,7 +702,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -776,7 +702,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
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
create_table "services", force: true do |t| create_table "services", force: :cascade do |t|
t.string "type" t.string "type"
t.string "title" t.string "title"
t.integer "project_id" t.integer "project_id"
...@@ -796,7 +722,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -796,7 +722,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree
add_index "services", ["template"], name: "index_services_on_template", using: :btree add_index "services", ["template"], name: "index_services_on_template", using: :btree
create_table "snippets", force: true do |t| create_table "snippets", force: :cascade do |t|
t.string "title" t.string "title"
t.text "content" t.text "content"
t.integer "author_id", null: false t.integer "author_id", null: false
...@@ -816,7 +742,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -816,7 +742,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree
add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree
create_table "subscriptions", force: true do |t| create_table "subscriptions", force: :cascade do |t|
t.integer "user_id" t.integer "user_id"
t.integer "subscribable_id" t.integer "subscribable_id"
t.string "subscribable_type" t.string "subscribable_type"
...@@ -827,7 +753,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -827,7 +753,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "subscriptions", ["subscribable_id", "subscribable_type", "user_id"], name: "subscriptions_user_id_and_ref_fields", unique: true, using: :btree add_index "subscriptions", ["subscribable_id", "subscribable_type", "user_id"], name: "subscriptions_user_id_and_ref_fields", unique: true, using: :btree
create_table "taggings", force: true do |t| create_table "taggings", force: :cascade do |t|
t.integer "tag_id" t.integer "tag_id"
t.integer "taggable_id" t.integer "taggable_id"
t.string "taggable_type" t.string "taggable_type"
...@@ -840,7 +766,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -840,7 +766,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree
add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree 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: true do |t| create_table "tags", force: :cascade do |t|
t.string "name" t.string "name"
t.integer "taggings_count", default: 0 t.integer "taggings_count", default: 0
end end
...@@ -848,8 +774,8 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -848,8 +774,8 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
create_table "users", force: true do |t| create_table "users", force: true do |t|
t.string "email", default: "", null: false t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false t.string "encrypted_password", default: "", null: false
t.string "reset_password_token" t.string "reset_password_token"
t.datetime "reset_password_sent_at" t.datetime "reset_password_sent_at"
t.datetime "remember_created_at" t.datetime "remember_created_at"
...@@ -914,7 +840,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -914,7 +840,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_index "users", ["username"], name: "index_users_on_username", using: :btree add_index "users", ["username"], name: "index_users_on_username", using: :btree
create_table "users_star_projects", force: true do |t| create_table "users_star_projects", force: :cascade do |t|
t.integer "project_id", null: false t.integer "project_id", null: false
t.integer "user_id", null: false t.integer "user_id", null: false
t.datetime "created_at" t.datetime "created_at"
...@@ -925,7 +851,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do ...@@ -925,7 +851,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "users_star_projects", ["user_id", "project_id"], name: "index_users_star_projects_on_user_id_and_project_id", unique: true, using: :btree add_index "users_star_projects", ["user_id", "project_id"], name: "index_users_star_projects_on_user_id_and_project_id", unique: true, using: :btree
add_index "users_star_projects", ["user_id"], name: "index_users_star_projects_on_user_id", using: :btree add_index "users_star_projects", ["user_id"], name: "index_users_star_projects_on_user_id", using: :btree
create_table "web_hooks", force: true do |t| create_table "web_hooks", force: :cascade do |t|
t.string "url" t.string "url"
t.integer "project_id" t.integer "project_id"
t.datetime "created_at" t.datetime "created_at"
......
# Quick Start # Quick Start
To start building projects with GitLab CI a few steps needs to be done. Starting from version 8.0, GitLab Continuous Integration (CI) is fully
integrated into GitLab itself and is enabled by default on all projects.
## 1. Install GitLab and CI This guide assumes that you:
First you need to have a working GitLab and GitLab CI instance. - have a working GitLab instance of version 8.0 or higher or are using
[GitLab.com](https://gitlab.com/users/sign_in)
- have a project in GitLab that you would like to use CI for
You can omit this step if you use [GitLab.com](https://GitLab.com/). In brief, the steps needed to have a working CI can be summed up to:
## 2. Create repository on GitLab 1. Create a new project
1. Add `.gitlab-ci.yml` to the git repository and push to GitLab
1. Configure a Runner
Once you login on your GitLab add a new repository where you will store your source code. From there on, on every push to your git repository the build will be
Push your application to that repository. automagically started by the Runner and will appear under the project's
`/builds` page.
## 3. Add project to CI Now, let's break it down to pieces and work on solving the GitLab CI puzzle.
The next part is to login to GitLab CI. ## Creating a `.gitlab-ci.yml` file
Point your browser to the URL you have set GitLab or use [gitlab.com/ci](https://gitlab.com/ci/).
On the first screen you will see a list of GitLab's projects that you have access to: Before you create `.gitlab-ci.yml` let's first explain in brief what this is
all about.
![Projects](projects.png) ### What is `.gitlab-ci.yml`
Click **Add Project to CI**. The `.gitlab-ci.yml` file is where you configure what CI does with your project.
This will create project in CI and authorize GitLab CI to fetch sources from GitLab. It lives in the root of your repository.
> GitLab CI creates unique token that is used to configure GitLab CI service in GitLab. On any push to your repository, GitLab will look for the `.gitlab-ci.yml`
> This token allows to access GitLab's repository and configures GitLab to trigger GitLab CI webhook on **Push events** and **Tag push events**. file and start builds on _Runners_ according to the contents of the file,
> You can see that token by going to Project's Settings > Services > GitLab CI. for that commit.
> You will see there token, the same token is assigned in GitLab CI settings of project.
## 4. Create project's configuration - .gitlab-ci.yml Because `.gitlab-ci.yml` is in the repository, it is version controlled,
old versions still build succesfully, forks can easily make use of CI,
branches can have separate builds and you have a single source of truth for CI.
You can read more about the reasons why we are using `.gitlab-ci.yml`
[in our blog about it][blog-ci].
The next: You have to define how your project will be built. **Note:** `.gitlab-ci.yml` is a [YAML](https://en.wikipedia.org/wiki/YAML) file
GitLab CI uses [YAML](https://en.wikipedia.org/wiki/YAML) file to store build configuration. so you have to pay extra attention to the identation. Always use spaces, not
You need to create `.gitlab-ci.yml` in root directory of your repository: tabs.
### Creating a simple `.gitlab-ci.yml` file
You need to create a file named `.gitlab-ci.yml` in the root directory of your
repository. Below is an example for a Ruby on Rails project.
```yaml ```yaml
before_script: before_script:
- bundle install - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
rspec: rspec:
script: script:
...@@ -49,71 +67,131 @@ rubocop: ...@@ -49,71 +67,131 @@ rubocop:
- bundle exec rubocop - bundle exec rubocop
``` ```
This is the simplest possible build configuration that will work for most Ruby applications: This is the simplest possible build configuration that will work for most Ruby
1. Define two jobs `rspec` and `rubocop` with two different commands to be executed. applications:
1. Before every job execute commands defined by `before_script`.
1. Define two jobs `rspec` and `rubocop` (the names are arbitrary) with
different commands to be executed.
1. Before every job, the commands defined by `before_script` are executed.
The `.gitlab-ci.yml` defines set of jobs with constrains how and when they should be run. The `.gitlab-ci.yml` file defines sets of jobs with constraints of how and when
The jobs are defined as top-level elements with name and always have to contain the `script`. they should be run. The jobs are defined as top-level elements with a name (in
Jobs are used to create builds, which are then picked by [runners](../runners/README.md) and executed within environment of the runner. our case `rspec` and `rubocop`) and always have to contain the `script` keyword.
What is important that each job is run independently from each other. Jobs are used to create builds, which are then picked by
[Runners](../runners/README.md) and executed within the environment of the Runner.
For more information and complete `.gitlab-ci.yml` syntax, please check the [Configuring project (.gitlab-ci.yml)](../yaml/README.md). What is important is that each job is run independently from each other.
## 5. Add file and push .gitlab-ci.yml to repository If you want to check whether your `.gitlab-ci.yml` file is valid, there is a
Lint tool under the page `/ci/lint` of your GitLab instance. You can also find
the link under **Settings > CI settings** in your project.
Once you created `.gitlab-ci.yml` you should add it to git repository and push it to GitLab. For more information and a complete `.gitlab-ci.yml` syntax, please check
[the documentation on .gitlab-ci.yml](../yaml/README.md).
### Push `.gitlab-ci.yml` to GitLab
Once you've created `.gitlab-ci.yml`, you should add it to your git repository
and push it to GitLab.
```bash ```bash
git add .gitlab-ci.yml git add .gitlab-ci.yml
git commit git commit -m "Add .gitlab-ci.yml"
git push origin master git push origin master
``` ```
If you refresh the project's page on GitLab CI you will notice a one new commit: Now if you go to the **Builds** page you will see that the builds are pending.
You can also go to the **Commits** page and notice the little clock icon next
to the commit SHA.
![New commit pending](img/new_commit.png)
Clicking on the clock icon you will be directed to the builds page for that
specific commit.
![Single commit builds page](img/single_commit_status_pending.png)
Notice that there are two jobs pending which are named after what we wrote in
`.gitlab-ci.yml`. The red triangle indicates that there is no Runner configured
yet for these builds.
The next step is to configure a Runner so that it picks the pending jobs.
## Configuring a Runner
In GitLab, Runners run the builds that you define in `.gitlab-ci.yml`.
A Runner can be a virtual machine, a VPS, a bare-metal machine, a docker
container or even a cluster of containers. GitLab and the Runners communicate
through an API, so the only needed requirement is that the machine on which the
Runner is configured to has Internet access.
A Runner can be specific to a certain project or serve multiple projects in
GitLab. If it serves all projects it's called a _Shared Runner_.
Find more information about different Runners in the
[Runners](../runners/README.md) documentation.
You can find whether any Runners are assigned to your project by going to
**Settings > Runners**. Setting up a Runner is easy and straightforward. The
official Runner supported by GitLab is written in Go and can be found at
<https://gitlab.com/gitlab-org/gitlab-ci-multi-runner>.
In order to have a functional Runner you need to follow two steps:
1. [Install it][runner-install]
2. [Configure it](../runners/README.md#registering-a-specific-runner)
Follow the links above to set up your own Runner or use a Shared Runner as
described in the next section.
For other types of unofficial Runners written in other languages, see the
[instructions for the various GitLab Runners](https://about.gitlab.com/gitlab-ci/#gitlab-runner).
Once the Runner has been set up, you should see it on the Runners page of your
project, following **Settings > Runners**.
![](new_commit.png) ![Activated runners](img/runners_activated.png)
However the commit has status **pending** which means that commit was not yet picked by runner. ### Shared Runners
## 6. Configure runner If you use [GitLab.com](https://gitlab.com/) you can use **Shared Runners**
provided by GitLab Inc.
In GitLab CI, Runners run your builds. These are special virtual machines that run on GitLab's infrastructure and can
A runner is a machine (can be virtual, bare-metal or VPS) that picks up builds through the coordinator API of GitLab CI. build any project.
A runner can be specific to a certain project or serve any project in GitLab CI. To enable **Shared Runners** you have to go to your project's
A runner that serves all projects is called a shared runner. **Settings > Runners** and click **Enable shared runners**.
More information about different runner types can be found in [Configuring runner](../runners/README.md).
To check if you have runners assigned to your project go to **Runners**. You will find there information how to setup project specific runner: [Read more on Shared Runners](../runners/README.md).
1. Install GitLab Runner software. Checkout the [GitLab Runner](https://about.gitlab.com/gitlab-ci/#gitlab-runner) section to install it. ## Seeing the status of your build
1. Specify following URL during runner setup: https://gitlab.com/ci/
1. Use the following registration token during setup: TOKEN
If you do it correctly your runner should be shown under **Runners activated for this project**: After configuring the Runner succesfully, you should see the status of your
last commit change from _pending_ to either _running_, _success_ or _failed_.
![](runners_activated.png) You can view all builds, by going to the **Builds** page in your project.
### Shared runners ![Commit status](img/builds_status.png)
If you use [gitlab.com/ci](https://gitlab.com/ci/) you can use **Shared runners** provided by GitLab Inc. By clicking on a Build ID, you will be able to see the log of that build.
These are special virtual machines that are run on GitLab's infrastructure that can build any project. This is important to diagnose why a build failed or acted differently than
To enable **Shared runners** you have to go to **Runners** and click **Enable shared runners** for this project. you expected.
## 7. Check status of commit ![Build log](img/build_log.png)
If everything went OK and you go to commit, the status of the commit should change from **pending** to either **running**, **success** or **failed**. You are also able to view the status of any commit in the various pages in
GitLab, such as **Commits** and **Merge Requests**.
![](commit_status.png) ## Next steps
You can click **Build ID** to view build log for specific job. Awesome! You started using CI in GitLab!
## 8. Congratulations! Next you can look into doing more with the CI. Many people are using GitLab
to package, containerize, test and deploy software.
You managed to build your first project using GitLab CI. Visit our various languages examples at <https://gitlab.com/groups/gitlab-examples>.
You may need to tune your `.gitlab-ci.yml` file to implement build plan for your project.
A few examples how it can be done you can find on [Examples](../examples/README.md) page.
GitLab CI also offers **the Lint** tool to verify validity of your `.gitlab-ci.yml` which can be useful to troubleshoot potential problems. [runner-install]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/tree/master#installation
The Lint is available from project's settings or by adding `/lint` to GitLab CI url. [blog-ci]: https://about.gitlab.com/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/
# Public access # Public access
GitLab allows you to open selected projects to be accessed **publicly** or **internally**. GitLab allows you to change your projects' visibility in order be accessed
**publicly** or **internally**.
Projects with either of these visibility levels will be listed in the [public access directory](/public). Projects with either of these visibility levels will be listed in the
public access directory (`/public` under your GitLab instance).
Here is the [GitLab.com example](https://gitlab.com/public).
Internal projects will only be available to authenticated users. Internal projects will only be available to authenticated users.
## Public projects ## Visibility of projects
### Public projects
Public projects can be cloned **without any** authentication. Public projects can be cloned **without any** authentication.
It will also be listed on the [public access directory](/public). They will also be listed on the public access directory (`/public`).
**Any logged in user** will have [Guest](../permissions/permissions) permissions on the repository. **Any logged in user** will have [Guest](../permissions/permissions)
permissions on the repository.
## Internal projects ### Internal projects
Internal projects can be cloned by any logged in user. Internal projects can be cloned by any logged in user.
It will also be listed on the [public access directory](/public) for logged in users. They will also be listed on the public access directory (`/public`) for logged
in users.
Any logged in user will have [Guest](../permissions/permissions) permissions on the repository. Any logged in user will have [Guest](../permissions/permissions) permissions on
the repository.
## How to change project visibility ### How to change project visibility
1. Go to your project dashboard 1. Go to your project's **Settings**
1. Click on the "Edit" tab 1. Change "Visibility Level" to either Public, Internal or Private
1. Change "Visibility Level"
## Visibility of users ## Visibility of users
The public page of users, located at `/u/username` is visible if either: The public page of a user, located at `/u/username`, is always visible whether
you are logged in or not.
When visiting the public page of a user, you can only see the projects which
you are privileged to.
- You are logged in. ## Visibility of groups
- You are logged out, and the target user is authorized to (is Guest, Reporter, etc.) at least one public project.
Otherwise, you will be redirected to the sign in page. The public page of a group, located at `/groups/groupname`, is always visible
to everyone.
When visiting the public page of an user, you will only see listed projects which you can view yourself. Logged out users will be able to see the description and the avatar of the
group as well as all public projects belonging to that group.
## Restricting the use of public or internal projects ## Restricting the use of public or internal projects
In the Admin area under Settings you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident. The restricted visibility settings do not apply to admin users. In the Admin area under **Settings** (`/admin/application_settings`), you can
restrict the use of visibility levels for users when they create a project or a
snippet. This is useful to prevent people exposing their repositories to public
by accident. The restricted visibility settings do not apply to admin users.
...@@ -274,9 +274,6 @@ sudo gitlab-rake gitlab:backup:restore BACKUP=1393513186 ...@@ -274,9 +274,6 @@ sudo gitlab-rake gitlab:backup:restore BACKUP=1393513186
# Start GitLab # Start GitLab
sudo gitlab-ctl start sudo gitlab-ctl start
# Create satellites
sudo gitlab-rake gitlab:satellites:create
# Check GitLab # Check GitLab
sudo gitlab-rake gitlab:check SANITIZE=true sudo gitlab-rake gitlab:check SANITIZE=true
``` ```
......
...@@ -121,6 +121,6 @@ git config --global credential.helper 'cache --timeout=3600' ...@@ -121,6 +121,6 @@ git config --global credential.helper 'cache --timeout=3600'
This will remember the credentials for an hour after which Git operations will require re-authentication. This will remember the credentials for an hour after which Git operations will require re-authentication.
If you are using OS X you can use `osxkeychain` to store and encrypt your credentials. For Windows, `wincred` is available. If you are using OS X you can use `osxkeychain` to store and encrypt your credentials. For Windows, you can use `wincred` or Microsoft's [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases).
More details about various methods of storing the user credentials can be found on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). More details about various methods of storing the user credentials can be found on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage).
\ No newline at end of file
Feature: Group Members
Background:
Given I sign in as "John Doe"
And "John Doe" is owner of group "Owned"
And "John Doe" is guest of group "Guest"
@javascript
Scenario: I should add user to group "Owned"
Given User "Mary Jane" exists
When I visit group "Owned" members page
And I select user "Mary Jane" from list with role "Reporter"
Then I should see user "Mary Jane" in team list
@javascript
Scenario: Add user to group
Given gitlab user "Mike"
When I visit group "Owned" members page
When I select "Mike" as "Reporter"
Then I should see "Mike" in team list as "Reporter"
@javascript
Scenario: Ignore add user to group when is already Owner
Given gitlab user "Mike"
When I visit group "Owned" members page
When I select "Mike" as "Reporter"
Then I should see "Mike" in team list as "Owner"
@javascript
Scenario: Invite user to group
When I visit group "Owned" members page
When I select "sjobs@apple.com" as "Reporter"
Then I should see "sjobs@apple.com" in team list as invited "Reporter"
@javascript
Scenario: Edit group member permissions
Given "Mary Jane" is guest of group "Owned"
And I visit group "Owned" members page
When I change the "Mary Jane" role to "Developer"
Then I should see "Mary Jane" as "Developer"
# Leave
@javascript
Scenario: Owner should be able to remove himself from group if he is not the last owner
Given "Mary Jane" is owner of group "Owned"
When I visit group "Owned" members page
Then I should see user "John Doe" in team list
Then I should see user "Mary Jane" in team list
When I click on the "Remove User From Group" button for "John Doe"
And I visit group "Owned" members page
Then I should not see user "John Doe" in team list
Then I should see user "Mary Jane" in team list
@javascript
Scenario: Owner should not be able to remove himself from group if he is the last owner
Given "Mary Jane" is guest of group "Owned"
When I visit group "Owned" members page
Then I should see user "John Doe" in team list
Then I should see user "Mary Jane" in team list
Then I should not see the "Remove User From Group" button for "John Doe"
@javascript
Scenario: Guest should be able to remove himself from group
Given "Mary Jane" is guest of group "Guest"
When I visit group "Guest" members page
Then I should see user "John Doe" in team list
Then I should see user "Mary Jane" in team list
When I click on the "Remove User From Group" button for "John Doe"
When I visit group "Guest" members page
Then I should not see user "John Doe" in team list
Then I should see user "Mary Jane" in team list
@javascript
Scenario: Guest should be able to remove himself from group even if he is the only user in the group
When I visit group "Guest" members page
Then I should see user "John Doe" in team list
When I click on the "Remove User From Group" button for "John Doe"
When I visit group "Guest" members page
Then I should not see user "John Doe" in team list
# Remove others
Scenario: Owner should be able to remove other users from group
Given "Mary Jane" is owner of group "Owned"
When I visit group "Owned" members page
Then I should see user "John Doe" in team list
Then I should see user "Mary Jane" in team list
When I click on the "Remove User From Group" button for "Mary Jane"
When I visit group "Owned" members page
Then I should see user "John Doe" in team list
Then I should not see user "Mary Jane" in team list
Scenario: Guest should not be able to remove other users from group
Given "Mary Jane" is guest of group "Guest"
When I visit group "Guest" members page
Then I should see user "John Doe" in team list
Then I should see user "Mary Jane" in team list
Then I should not see the "Remove User From Group" button for "Mary Jane"
Scenario: Search member by name
Given "Mary Jane" is guest of group "Guest"
And I visit group "Guest" members page
When I search for 'Mary' member
Then I should see user "Mary Jane" in team list
Then I should not see user "John Doe" in team list
Feature: Group Milestones
Background:
Given I sign in as "John Doe"
And "John Doe" is owner of group "Owned"
Scenario: I should see group "Owned" milestone index page with no milestones
When I visit group "Owned" page
And I click on group milestones
Then I should see group milestones index page has no milestones
Scenario: I should see group "Owned" milestone index page with milestones
Given Group has projects with milestones
When I visit group "Owned" page
And I click on group milestones
Then I should see group milestones index page with milestones
Scenario: I should see group "Owned" milestone show page
Given Group has projects with milestones
When I visit group "Owned" page
And I click on group milestones
And I click on one group milestone
Then I should see group milestone with descriptions and expiry date
And I should see group milestone with all issues and MRs assigned to that milestone
Scenario: Create multiple milestones with one form
Given I visit group "Owned" milestones page
And I click new milestone button
And I fill milestone name
When I press create mileston button
Then milestone in each project should be created
...@@ -186,6 +186,8 @@ Feature: Groups ...@@ -186,6 +186,8 @@ Feature: Groups
When I press create mileston button When I press create mileston button
Then milestone in each project should be created Then milestone in each project should be created
# Group projects in settings # Group projects in settings
Scenario: I should see all projects in the project list in settings Scenario: I should see all projects in the project list in settings
Given Group "Owned" has archived project Given Group "Owned" has archived project
......
...@@ -13,14 +13,12 @@ Feature: Project Team Management ...@@ -13,14 +13,12 @@ Feature: Project Team Management
@javascript @javascript
Scenario: Add user to project Scenario: Add user to project
Given I click link "Add members" When I select "Mike" as "Reporter"
And I select "Mike" as "Reporter"
Then I should see "Mike" in team list as "Reporter" Then I should see "Mike" in team list as "Reporter"
@javascript @javascript
Scenario: Invite user to project Scenario: Invite user to project
Given I click link "Add members" When I select "sjobs@apple.com" as "Reporter"
And I select "sjobs@apple.com" as "Reporter"
Then I should see "sjobs@apple.com" in team list as invited "Reporter" Then I should see "sjobs@apple.com" in team list as invited "Reporter"
@javascript @javascript
......
class Spinach::Features::GroupMembers < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedGroup
include SharedUser
include Select2Helper
step 'I select "Mike" as "Reporter"' do
user = User.find_by(name: "Mike")
page.within ".users-group-form" do
select2(user.id, from: "#user_ids", multiple: true)
select "Reporter", from: "access_level"
end
click_button "Add users to group"
end
step 'I select "Mike" as "Master"' do
user = User.find_by(name: "Mike")
page.within ".users-group-form" do
select2(user.id, from: "#user_ids", multiple: true)
select "Master", from: "access_level"
end
click_button "Add users to group"
end
step 'I should see "Mike" in team list as "Reporter"' do
page.within '.content-list' do
expect(page).to have_content('Mike')
expect(page).to have_content('Reporter')
end
end
step 'I should see "Mike" in team list as "Owner"' do
page.within '.content-list' do
expect(page).to have_content('Mike')
expect(page).to have_content('Owner')
end
end
step 'I select "sjobs@apple.com" as "Reporter"' do
page.within ".users-group-form" do
select2("sjobs@apple.com", from: "#user_ids", multiple: true)
select "Reporter", from: "access_level"
end
click_button "Add users to group"
end
step 'I should see "sjobs@apple.com" in team list as invited "Reporter"' do
page.within '.content-list' do
expect(page).to have_content('sjobs@apple.com')
expect(page).to have_content('invited')
expect(page).to have_content('Reporter')
end
end
step 'I select user "Mary Jane" from list with role "Reporter"' do
user = User.find_by(name: "Mary Jane") || create(:user, name: "Mary Jane")
page.within ".users-group-form" do
select2(user.id, from: "#user_ids", multiple: true)
select "Reporter", from: "access_level"
end
click_button "Add users to group"
end
step 'I should see user "John Doe" in team list' do
expect(group_members_list).to have_content("John Doe")
end
step 'I should not see user "John Doe" in team list' do
expect(group_members_list).not_to have_content("John Doe")
end
step 'I should see user "Mary Jane" in team list' do
expect(group_members_list).to have_content("Mary Jane")
end
step 'I should not see user "Mary Jane" in team list' do
expect(group_members_list).not_to have_content("Mary Jane")
end
step 'I click on the "Remove User From Group" button for "John Doe"' do
find(:css, 'li', text: "John Doe").find(:css, 'a.btn-remove').click
# poltergeist always confirms popups.
end
step 'I click on the "Remove User From Group" button for "Mary Jane"' do
find(:css, 'li', text: "Mary Jane").find(:css, 'a.btn-remove').click
# poltergeist always confirms popups.
end
step 'I should not see the "Remove User From Group" button for "John Doe"' do
expect(find(:css, 'li', text: "John Doe")).not_to have_selector(:css, 'a.btn-remove')
# poltergeist always confirms popups.
end
step 'I should not see the "Remove User From Group" button for "Mary Jane"' do
expect(find(:css, 'li', text: "Mary Jane")).not_to have_selector(:css, 'a.btn-remove')
# poltergeist always confirms popups.
end
step 'I search for \'Mary\' member' do
page.within '.member-search-form' do
fill_in 'search', with: 'Mary'
click_button 'Search'
end
end
step 'I change the "Mary Jane" role to "Developer"' do
member = mary_jane_member
page.within "#group_member_#{member.id}" do
find(".js-toggle-button").click
page.within "#edit_group_member_#{member.id}" do
select 'Developer', from: 'group_member_access_level'
click_on 'Save'
end
end
end
step 'I should see "Mary Jane" as "Developer"' do
member = mary_jane_member
page.within "#group_member_#{member.id}" do
page.within '.member-access-level' do
expect(page).to have_content "Developer"
end
end
end
private
def mary_jane_member
user = User.find_by(name: "Mary Jane")
owned_group.members.find_by(user_id: user.id)
end
def group_members_list
find(".panel .content-list")
end
end
class Spinach::Features::GroupMilestones < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedGroup
include SharedUser
step 'I click on group milestones' do
click_link 'Milestones'
end
step 'I should see group milestones index page has no milestones' do
expect(page).to have_content('No milestones to show')
end
step 'Group has projects with milestones' do
group_milestone
end
step 'I should see group milestones index page with milestones' do
expect(page).to have_content('Version 7.2')
expect(page).to have_content('GL-113')
expect(page).to have_link('3 Issues', href: issues_group_path("owned", milestone_title: "Version 7.2"))
expect(page).to have_link('0 Merge Requests', href: merge_requests_group_path("owned", milestone_title: "GL-113"))
end
step 'I click on one group milestone' do
click_link 'GL-113'
end
step 'I should see group milestone with descriptions and expiry date' do
expect(page).to have_content('expires at Aug 20, 2114')
end
step 'I should see group milestone with all issues and MRs assigned to that milestone' do
expect(page).to have_content('Milestone GL-113')
expect(page).to have_content('Progress: 0 closed – 3 open')
issue = Milestone.find_by(name: 'GL-113').issues.first
expect(page).to have_link(issue.title, href: namespace_project_issue_path(issue.project.namespace, issue.project, issue))
end
step 'I fill milestone name' do
fill_in 'milestone_title', with: 'v2.9.0'
end
step 'I click new milestone button' do
click_link "New Milestone"
end
step 'I press create mileston button' do
click_button "Create Milestone"
end
step 'milestone in each project should be created' do
group = Group.find_by(name: 'Owned')
expect(page).to have_content "Milestone v2.9.0"
expect(group.projects).to be_present
group.projects.each do |project|
expect(page).to have_content project.name
end
end
private
def group_milestone
group = owned_group
%w(gitlabhq gitlab-ci cookbook-gitlab).each do |path|
project = create :project, path: path, group: group
milestone = create :milestone, title: "Version 7.2", project: project
create :issue,
project: project,
assignee: current_user,
author: current_user,
milestone: milestone
milestone = create :milestone,
title: "GL-113",
project: project,
due_date: '2114-08-20',
description: 'Lorem Ipsum is simply dummy text'
create :issue,
project: project,
assignee: current_user,
author: current_user,
milestone: milestone
end
end
end
...@@ -26,7 +26,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -26,7 +26,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
end end
step 'Group "Owned" has a public project "Public-project"' do step 'Group "Owned" has a public project "Public-project"' do
group = Group.find_by(name: "Owned") group = owned_group
@project = create :empty_project, :public, @project = create :empty_project, :public,
group: group, group: group,
...@@ -91,7 +91,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -91,7 +91,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
end end
step 'I should see group "Owned" projects list' do step 'I should see group "Owned" projects list' do
Group.find_by(name: "Owned").projects.each do |project| owned_group.projects.each do |project|
expect(page).to have_link project.name expect(page).to have_link project.name
end end
end end
...@@ -214,12 +214,12 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -214,12 +214,12 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
step 'I change group "Owned" avatar' do step 'I change group "Owned" avatar' do
attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')) attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif'))
click_button "Save group" click_button "Save group"
Group.find_by(name: "Owned").reload owned_group.reload
end end
step 'I should see new group "Owned" avatar' do step 'I should see new group "Owned" avatar' do
expect(Group.find_by(name: "Owned").avatar).to be_instance_of AvatarUploader expect(owned_group.avatar).to be_instance_of AvatarUploader
expect(Group.find_by(name: "Owned").avatar.url).to eq "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/banana_sample.gif" expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/banana_sample.gif"
end end
step 'I should see the "Remove avatar" button' do step 'I should see the "Remove avatar" button' do
...@@ -229,16 +229,16 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -229,16 +229,16 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
step 'I have group "Owned" avatar' do step 'I have group "Owned" avatar' do
attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')) attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif'))
click_button "Save group" click_button "Save group"
Group.find_by(name: "Owned").reload owned_group.reload
end end
step 'I remove group "Owned" avatar' do step 'I remove group "Owned" avatar' do
click_link "Remove avatar" click_link "Remove avatar"
Group.find_by(name: "Owned").reload owned_group.reload
end end
step 'I should not see group "Owned" avatar' do step 'I should not see group "Owned" avatar' do
expect(Group.find_by(name: "Owned").avatar?).to eq false expect(owned_group.avatar?).to eq false
end end
step 'I should not see the "Remove avatar" button' do step 'I should not see the "Remove avatar" button' do
...@@ -337,14 +337,36 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -337,14 +337,36 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
end end
end end
protected step 'LDAP enabled' do
allow(Gitlab.config.ldap).to receive(:enabled).and_return(true)
end
step 'LDAP disabled' do
allow(Gitlab.config.ldap).to receive(:enabled).and_return(false)
end
step 'I add a new LDAP synchronization' do
page.within('form#new_ldap_group_link') do
find('#ldap_group_link_cn', visible: false).set('my-group-cn')
# fill_in('LDAP Group cn', with: 'my-group-cn', visible: false)
select 'Developer', from: "ldap_group_link_group_access"
click_button 'Add synchronization'
end
end
step 'I see a new LDAP synchronization listed' do
expect(page).not_to have_content('No synchronizations yet')
expect(page).to have_content('As Developer on ldap server')
end
private
def assigned_to_me(key) def assigned_to_me(key)
project.send(key).where(assignee_id: current_user.id) project.send(key).where(assignee_id: current_user.id)
end end
def project def project
Group.find_by(name: "Owned").projects.first owned_group.projects.first
end end
def group_milestone def group_milestone
...@@ -412,26 +434,4 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -412,26 +434,4 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
author: current_user, author: current_user,
milestone: milestone2_project3 milestone: milestone2_project3
end end
step 'LDAP enabled' do
allow(Gitlab.config.ldap).to receive(:enabled).and_return(true)
end
step 'LDAP disabled' do
allow(Gitlab.config.ldap).to receive(:enabled).and_return(false)
end
step 'I add a new LDAP synchronization' do
page.within('form#new_ldap_group_link') do
find('#ldap_group_link_cn', visible: false).set('my-group-cn')
# fill_in('LDAP Group cn', with: 'my-group-cn', visible: false)
select 'Developer', from: "ldap_group_link_group_access"
click_button 'Add synchronization'
end
end
step 'I see a new LDAP synchronization listed' do
expect(page).not_to have_content('No synchronizations yet')
expect(page).to have_content('As Developer on ldap server')
end
end end
...@@ -15,10 +15,6 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps ...@@ -15,10 +15,6 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps
expect(page).to have_content(user.username) expect(page).to have_content(user.username)
end end
step 'I click link "Add members"' do
find(:css, 'button.btn-new').click
end
step 'I select "Mike" as "Reporter"' do step 'I select "Mike" as "Reporter"' do
user = User.find_by(name: "Mike") user = User.find_by(name: "Mike")
......
...@@ -45,4 +45,8 @@ module SharedGroup ...@@ -45,4 +45,8 @@ module SharedGroup
project.team << [user, :master] project.team << [user, :master]
@project_count += 1 @project_count += 1
end end
def owned_group
@owned_group ||= Group.find_by(name: "Owned")
end
end end
...@@ -9,6 +9,10 @@ module SharedUser ...@@ -9,6 +9,10 @@ module SharedUser
user_exists("Mary Jane", { username: "mary_jane" }) user_exists("Mary Jane", { username: "mary_jane" })
end end
step 'gitlab user "Mike"' do
create(:user, name: "Mike")
end
protected protected
def user_exists(name, options = {}) def user_exists(name, options = {})
......
...@@ -16,6 +16,17 @@ module Gitlab ...@@ -16,6 +16,17 @@ module Gitlab
def trigger(gl_id, oldrev, newrev, ref) def trigger(gl_id, oldrev, newrev, ref)
return true unless exists? return true unless exists?
case name
when "pre-receive", "post-receive"
call_receive_hook(gl_id, oldrev, newrev, ref)
when "update"
call_update_hook(gl_id, oldrev, newrev, ref)
end
end
private
def call_receive_hook(gl_id, oldrev, newrev, ref)
changes = [oldrev, newrev, ref].join(" ") changes = [oldrev, newrev, ref].join(" ")
# function will return true if succesful # function will return true if succesful
...@@ -54,6 +65,12 @@ module Gitlab ...@@ -54,6 +65,12 @@ module Gitlab
exit_status exit_status
end end
def call_update_hook(gl_id, oldrev, newrev, ref)
Dir.chdir(repo_path) do
system({ 'GL_ID' => gl_id }, path, ref, oldrev, newrev)
end
end
end end
end end
end end
...@@ -46,7 +46,7 @@ module Gitlab ...@@ -46,7 +46,7 @@ module Gitlab
end end
def github_options def github_options
config["args"]["client_options"].deep_symbolize_keys OmniAuth::Strategies::GitHub.default_options[:client_options].to_h.symbolize_keys
end end
end end
end end
......
...@@ -75,7 +75,7 @@ module Gitlab ...@@ -75,7 +75,7 @@ module Gitlab
end end
def gitlab_options def gitlab_options
OmniAuth::Strategies::GitLab.default_options[:client_options].symbolize_keys OmniAuth::Strategies::GitLab.default_options[:client_options].to_h.symbolize_keys
end end
end end
end end
......
...@@ -60,8 +60,7 @@ module Gitlab ...@@ -60,8 +60,7 @@ module Gitlab
def url_for_label(project, label) def url_for_label(project, label)
h = Gitlab::Application.routes.url_helpers h = Gitlab::Application.routes.url_helpers
h.namespace_project_issues_path(project.namespace, project, h.namespace_project_issues_path(project.namespace, project,
label_name: label.name, label_name: label.name)
only_path: context[:only_path])
end end
def render_colored_label(label) def render_colored_label(label)
......
...@@ -14,7 +14,7 @@ module Gitlab ...@@ -14,7 +14,7 @@ module Gitlab
def self.mute_mailer def self.mute_mailer
code = <<-eos code = <<-eos
def Notify.delay def Notify.deliver_later
self self
end end
eos eos
......
...@@ -36,6 +36,11 @@ module Gitlab ...@@ -36,6 +36,11 @@ module Gitlab
@duration ||= started_at && finished_at ? finished_at - started_at : 0 @duration ||= started_at && finished_at ? finished_at - started_at : 0
end end
# Returns the total query duration in seconds.
def query_duration
@query_duration ||= @queries.map { |q| q.duration }.inject(:+) / 1000.0
end
def to_param def to_param
@id @id
end end
......
...@@ -114,24 +114,28 @@ server { ...@@ -114,24 +114,28 @@ server {
} }
location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects { location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse; error_page 418 = @gitlab-workhorse;
return 418; return 418;
} }
location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ { location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse; error_page 418 = @gitlab-workhorse;
return 418; return 418;
} }
location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive { location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse; error_page 418 = @gitlab-workhorse;
return 418; return 418;
} }
location ~ ^/api/v3/projects/.*/repository/archive { location ~ ^/api/v3/projects/.*/repository/archive {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse; error_page 418 = @gitlab-workhorse;
return 418; return 418;
...@@ -139,16 +143,18 @@ server { ...@@ -139,16 +143,18 @@ server {
# Build artifacts should be submitted to this location # Build artifacts should be submitted to this location
location ~ ^/[\w\.-]+/[\w\.-]+/builds/download { location ~ ^/[\w\.-]+/[\w\.-]+/builds/download {
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block client_max_body_size 0;
error_page 418 = @gitlab-workhorse; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
return 418; error_page 418 = @gitlab-workhorse;
return 418;
} }
# Build artifacts should be submitted to this location # Build artifacts should be submitted to this location
location ~ /ci/api/v1/builds/[0-9]+/artifacts { location ~ /ci/api/v1/builds/[0-9]+/artifacts {
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block client_max_body_size 0;
error_page 418 = @gitlab-workhorse; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
return 418; error_page 418 = @gitlab-workhorse;
return 418;
} }
location @gitlab-workhorse { location @gitlab-workhorse {
......
...@@ -161,24 +161,28 @@ server { ...@@ -161,24 +161,28 @@ server {
} }
location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects { location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse; error_page 418 = @gitlab-workhorse;
return 418; return 418;
} }
location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ { location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse; error_page 418 = @gitlab-workhorse;
return 418; return 418;
} }
location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive { location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse; error_page 418 = @gitlab-workhorse;
return 418; return 418;
} }
location ~ ^/api/v3/projects/.*/repository/archive { location ~ ^/api/v3/projects/.*/repository/archive {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse; error_page 418 = @gitlab-workhorse;
return 418; return 418;
...@@ -186,16 +190,18 @@ server { ...@@ -186,16 +190,18 @@ server {
# Build artifacts should be submitted to this location # Build artifacts should be submitted to this location
location ~ ^/[\w\.-]+/[\w\.-]+/builds/download { location ~ ^/[\w\.-]+/[\w\.-]+/builds/download {
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block client_max_body_size 0;
error_page 418 = @gitlab-workhorse; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
return 418; error_page 418 = @gitlab-workhorse;
return 418;
} }
# Build artifacts should be submitted to this location # Build artifacts should be submitted to this location
location ~ /ci/api/v1/builds/[0-9]+/artifacts { location ~ /ci/api/v1/builds/[0-9]+/artifacts {
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block client_max_body_size 0;
error_page 418 = @gitlab-workhorse; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
return 418; error_page 418 = @gitlab-workhorse;
return 418;
} }
location @gitlab-workhorse { location @gitlab-workhorse {
......
...@@ -2,16 +2,6 @@ module Gitlab ...@@ -2,16 +2,6 @@ module Gitlab
class TaskAbortedByUserError < StandardError; end class TaskAbortedByUserError < StandardError; end
end end
unless STDOUT.isatty
module Colored
extend self
def colorize(string, options={})
string
end
end
end
namespace :gitlab do namespace :gitlab do
# Ask if the user wants to continue # Ask if the user wants to continue
...@@ -103,7 +93,7 @@ namespace :gitlab do ...@@ -103,7 +93,7 @@ namespace :gitlab do
gitlab_user = Gitlab.config.gitlab.user gitlab_user = Gitlab.config.gitlab.user
current_user = run(%W(whoami)).chomp current_user = run(%W(whoami)).chomp
unless current_user == gitlab_user unless current_user == gitlab_user
puts "#{Colored.color(:black)+Colored.color(:on_yellow)} Warning #{Colored.extra(:clear)}" puts " Warning ".colorize(:black).on_yellow
puts " You are running as user #{current_user.magenta}, we hope you know what you are doing." puts " You are running as user #{current_user.magenta}, we hope you know what you are doing."
puts " Things may work\/fail for the wrong reasons." puts " Things may work\/fail for the wrong reasons."
puts " For correct results you should run this as user #{gitlab_user.magenta}." puts " For correct results you should run this as user #{gitlab_user.magenta}."
......
#!/bin/bash #!/bin/bash
if [ -f /.dockerinit ]; then if [ -f /.dockerinit ]; then
wget -q http://ftp.de.debian.org/debian/pool/main/p/phantomjs/phantomjs_1.9.0-1+b1_amd64.deb wget -q https://gitlab.com/axil/phantomjs-debian/raw/master/phantomjs_1.9.8-0jessie_amd64.deb
dpkg -i phantomjs_1.9.0-1+b1_amd64.deb dpkg -i phantomjs_1.9.8-0jessie_amd64.deb
apt-get update -qq apt-get update -qq
apt-get install -y -qq libicu-dev libkrb5-dev cmake nodejs postgresql-client mysql-client apt-get install -y -qq libicu-dev libkrb5-dev cmake nodejs postgresql-client mysql-client
......
...@@ -18,27 +18,31 @@ describe AbuseReportsController do ...@@ -18,27 +18,31 @@ describe AbuseReportsController do
end end
it "sends a notification email" do it "sends a notification email" do
post :create, perform_enqueued_jobs do
abuse_report: {
user_id: user.id,
message: message
}
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
it "saves the abuse report" do
expect do
post :create, post :create,
abuse_report: { abuse_report: {
user_id: user.id, user_id: user.id,
message: message message: message
} }
end.to change { AbuseReport.count }.by(1)
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
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
end end
end end
......
...@@ -69,6 +69,21 @@ describe Projects::CommitController do ...@@ -69,6 +69,21 @@ describe Projects::CommitController do
expect(response.body).to start_with("diff --git") expect(response.body).to start_with("diff --git")
end end
it "should really only be a git diff without whitespace changes" do
get(:show,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
id: '66eceea0db202bb39c4e445e8ca28689645366c5',
# id: commit.id,
format: format,
w: 1)
expect(response.body).to start_with("diff --git")
# without whitespace option, there are more than 2 diff_splits
diff_splits = assigns(:diffs)[0].diff.split("\n")
expect(diff_splits.length).to be <= 2
end
end end
describe "as patch" do describe "as patch" do
......
...@@ -88,6 +88,22 @@ describe ProjectsController do ...@@ -88,6 +88,22 @@ describe ProjectsController do
end end
end end
describe "#destroy" do
let(:admin) { create(:admin) }
it "redirects to the dashboard" do
controller.instance_variable_set(:@project, project)
sign_in(admin)
orig_id = project.id
delete :destroy, namespace_id: project.namespace.path, id: project.path
expect { Project.find(orig_id) }.to raise_error(ActiveRecord::RecordNotFound)
expect(response.status).to eq(302)
expect(response).to redirect_to(dashboard_projects_path)
end
end
describe "POST #toggle_star" do describe "POST #toggle_star" do
it "toggles star if user is signed in" do it "toggles star if user is signed in" do
sign_in(user) sign_in(user)
......
...@@ -115,4 +115,119 @@ describe SnippetsController do ...@@ -115,4 +115,119 @@ describe SnippetsController do
end end
end end
end end
describe 'GET #raw' do
let(:user) { create(:user) }
context 'when the personal snippet is private' do
let(:personal_snippet) { create(:personal_snippet, :private, author: user) }
context 'when signed in' do
before do
sign_in(user)
end
context 'when signed in user is not the author' do
let(:other_author) { create(:author) }
let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) }
it 'responds with status 404' do
get :raw, id: other_personal_snippet.to_param
expect(response.status).to eq(404)
end
end
context 'when signed in user is the author' do
it 'renders the raw snippet' do
get :raw, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response.status).to eq(200)
end
end
end
context 'when not signed in' do
it 'redirects to the sign in page' do
get :raw, id: personal_snippet.to_param
expect(response).to redirect_to(new_user_session_path)
end
end
end
context 'when the personal snippet is internal' do
let(:personal_snippet) { create(:personal_snippet, :internal, author: user) }
context 'when signed in' do
before do
sign_in(user)
end
it 'renders the raw snippet' do
get :raw, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response.status).to eq(200)
end
end
context 'when not signed in' do
it 'redirects to the sign in page' do
get :raw, id: personal_snippet.to_param
expect(response).to redirect_to(new_user_session_path)
end
end
end
context 'when the personal snippet is public' do
let(:personal_snippet) { create(:personal_snippet, :public, author: user) }
context 'when signed in' do
before do
sign_in(user)
end
it 'renders the raw snippet' do
get :raw, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response.status).to eq(200)
end
end
context 'when not signed in' do
it 'renders the raw snippet' do
get :raw, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response.status).to eq(200)
end
end
end
context 'when the personal snippet does not exist' do
context 'when signed in' do
before do
sign_in(user)
end
it 'responds with status 404' do
get :raw, id: 'doesntexist'
expect(response.status).to eq(404)
end
end
context 'when not signed in' do
it 'responds with status 404' do
get :raw, id: 'doesntexist'
expect(response.status).to eq(404)
end
end
end
end
end end
...@@ -87,13 +87,16 @@ describe "Admin::Users", feature: true do ...@@ -87,13 +87,16 @@ describe "Admin::Users", feature: true do
end end
it "should call send mail" do it "should call send mail" do
expect(Notify).to receive(:new_user_email) expect_any_instance_of(NotificationService).to receive(:new_user)
click_button "Create user" click_button "Create user"
end end
it "should send valid email to user with email & password" do it "should send valid email to user with email & password" do
click_button "Create user" perform_enqueued_jobs do
click_button "Create user"
end
user = User.find_by(username: 'bang') user = User.find_by(username: 'bang')
email = ActionMailer::Base.deliveries.last email = ActionMailer::Base.deliveries.last
expect(email.subject).to have_content('Account was created') expect(email.subject).to have_content('Account was created')
......
...@@ -59,7 +59,7 @@ describe ApplicationHelper do ...@@ -59,7 +59,7 @@ describe ApplicationHelper do
avatar_url = "http://localhost/uploads/project/avatar/#{project.id}/banana_sample.gif" avatar_url = "http://localhost/uploads/project/avatar/#{project.id}/banana_sample.gif"
expect(helper.project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s). expect(helper.project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s).
to eq "<img alt=\"Banana sample\" src=\"#{avatar_url}\" />" to eq "<img src=\"#{avatar_url}\" alt=\"Banana sample\" />"
end end
it 'should give uploaded icon when present' do it 'should give uploaded icon when present' do
...@@ -95,9 +95,9 @@ describe ApplicationHelper do ...@@ -95,9 +95,9 @@ describe ApplicationHelper do
end end
it 'should call gravatar_icon when no User exists with the given email' do it 'should call gravatar_icon when no User exists with the given email' do
expect(helper).to receive(:gravatar_icon).with('foo@example.com', 20) expect(helper).to receive(:gravatar_icon).with('foo@example.com', 20, 2)
helper.avatar_icon('foo@example.com', 20) helper.avatar_icon('foo@example.com', 20, 2)
end end
describe 'using a User' do describe 'using a User' do
...@@ -150,15 +150,19 @@ describe ApplicationHelper do ...@@ -150,15 +150,19 @@ describe ApplicationHelper do
stub_gravatar_setting(plain_url: 'http://example.local/?s=%{size}&hash=%{hash}') stub_gravatar_setting(plain_url: 'http://example.local/?s=%{size}&hash=%{hash}')
expect(gravatar_icon(user_email, 20)). expect(gravatar_icon(user_email, 20)).
to eq('http://example.local/?s=20&hash=b58c6f14d292556214bd64909bcdb118') to eq('http://example.local/?s=40&hash=b58c6f14d292556214bd64909bcdb118')
end end
it 'accepts a custom size argument' do it 'accepts a custom size argument' do
expect(helper.gravatar_icon(user_email, 64)).to include '?s=64' expect(helper.gravatar_icon(user_email, 64)).to include '?s=128'
end end
it 'defaults size to 40 when given an invalid size' do it 'defaults size to 40@2x when given an invalid size' do
expect(helper.gravatar_icon(user_email, nil)).to include '?s=40' expect(helper.gravatar_icon(user_email, nil)).to include '?s=80'
end
it 'accepts a scaling factor' do
expect(helper.gravatar_icon(user_email, 40, 3)).to include '?s=120'
end end
it 'ignores case and surrounding whitespace' do it 'ignores case and surrounding whitespace' do
......
...@@ -71,7 +71,7 @@ module Gitlab::Markdown ...@@ -71,7 +71,7 @@ module Gitlab::Markdown
doc = filter("See #{reference}") doc = filter("See #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls. expect(doc.css('a').first.attr('href')).to eq urls.
namespace_project_issues_url(project.namespace, project, label_name: label.name) namespace_project_issues_path(project.namespace, project, label_name: label.name)
end end
it 'links with adjacent text' do it 'links with adjacent text' do
...@@ -94,7 +94,7 @@ module Gitlab::Markdown ...@@ -94,7 +94,7 @@ module Gitlab::Markdown
doc = filter("See #{reference}") doc = filter("See #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls. expect(doc.css('a').first.attr('href')).to eq urls.
namespace_project_issues_url(project.namespace, project, label_name: label.name) namespace_project_issues_path(project.namespace, project, label_name: label.name)
expect(doc.text).to eq 'See gfm' expect(doc.text).to eq 'See gfm'
end end
...@@ -118,7 +118,7 @@ module Gitlab::Markdown ...@@ -118,7 +118,7 @@ module Gitlab::Markdown
doc = filter("See #{reference}") doc = filter("See #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls. expect(doc.css('a').first.attr('href')).to eq urls.
namespace_project_issues_url(project.namespace, project, label_name: label.name) namespace_project_issues_path(project.namespace, project, label_name: label.name)
expect(doc.text).to eq 'See gfm references' expect(doc.text).to eq 'See gfm references'
end end
......
...@@ -84,6 +84,19 @@ describe Gitlab::Sherlock::Transaction do ...@@ -84,6 +84,19 @@ describe Gitlab::Sherlock::Transaction do
end end
end end
describe '#query_duration' do
it 'returns the total query duration in seconds' do
time = Time.now
query1 = Gitlab::Sherlock::Query.new('SELECT 1', time, time + 5)
query2 = Gitlab::Sherlock::Query.new('SELECT 2', time, time + 2)
transaction.queries << query1
transaction.queries << query2
expect(transaction.query_duration).to be_within(0.1).of(7.0)
end
end
describe '#to_param' do describe '#to_param' do
it 'returns the transaction ID' do it 'returns the transaction ID' do
expect(transaction.to_param).to eq(transaction.id) expect(transaction.to_param).to eq(transaction.id)
......
...@@ -77,6 +77,32 @@ describe Notify do ...@@ -77,6 +77,32 @@ describe Notify do
end end
end end
shared_examples 'it should have Gmail Actions links' do
it { is_expected.to have_body_text /ViewAction/ }
end
shared_examples 'it should not have Gmail Actions links' do
it { is_expected.to_not have_body_text /ViewAction/ }
end
shared_examples 'it should show Gmail Actions View Issue link' do
it_behaves_like 'it should have Gmail Actions links'
it { is_expected.to have_body_text /View Issue/ }
end
shared_examples 'it should show Gmail Actions View Merge request link' do
it_behaves_like 'it should have Gmail Actions links'
it { is_expected.to have_body_text /View Merge request/ }
end
shared_examples 'it should show Gmail Actions View Commit link' do
it_behaves_like 'it should have Gmail Actions links'
it { is_expected.to have_body_text /View Commit/ }
end
describe 'for new users, the email' do describe 'for new users, the email' do
let(:example_site_path) { root_path } let(:example_site_path) { root_path }
let(:new_user) { create(:user, email: new_user_address, created_by_id: 1) } let(:new_user) { create(:user, email: new_user_address, created_by_id: 1) }
...@@ -87,6 +113,7 @@ describe Notify do ...@@ -87,6 +113,7 @@ describe Notify do
it_behaves_like 'an email sent from GitLab' it_behaves_like 'an email sent from GitLab'
it_behaves_like 'a new user email', new_user_address it_behaves_like 'a new user email', new_user_address
it_behaves_like 'it should not have Gmail Actions links'
it 'contains the password text' do it 'contains the password text' do
is_expected.to have_body_text /Click here to set your password/ is_expected.to have_body_text /Click here to set your password/
...@@ -115,6 +142,7 @@ describe Notify do ...@@ -115,6 +142,7 @@ describe Notify do
it_behaves_like 'an email sent from GitLab' it_behaves_like 'an email sent from GitLab'
it_behaves_like 'a new user email', new_user_address it_behaves_like 'a new user email', new_user_address
it_behaves_like 'it should not have Gmail Actions links'
it 'should not contain the new user\'s password' do it 'should not contain the new user\'s password' do
is_expected.not_to have_body_text /password/ is_expected.not_to have_body_text /password/
...@@ -127,6 +155,7 @@ describe Notify do ...@@ -127,6 +155,7 @@ describe Notify do
subject { Notify.new_ssh_key_email(key.id) } subject { Notify.new_ssh_key_email(key.id) }
it_behaves_like 'an email sent from GitLab' it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent to the new user' do it 'is sent to the new user' do
is_expected.to deliver_to key.user.email is_expected.to deliver_to key.user.email
...@@ -150,6 +179,8 @@ describe Notify do ...@@ -150,6 +179,8 @@ describe Notify do
subject { Notify.new_email_email(email.id) } subject { Notify.new_email_email(email.id) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent to the new user' do it 'is sent to the new user' do
is_expected.to deliver_to email.user.email is_expected.to deliver_to email.user.email
end end
...@@ -194,6 +225,7 @@ describe Notify do ...@@ -194,6 +225,7 @@ describe Notify do
it_behaves_like 'an assignee email' it_behaves_like 'an assignee email'
it_behaves_like 'an email starting a new thread', 'issue' it_behaves_like 'an email starting a new thread', 'issue'
it_behaves_like 'it should show Gmail Actions View Issue link'
it 'has the correct subject' do it 'has the correct subject' do
is_expected.to have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/ is_expected.to have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/
...@@ -207,6 +239,8 @@ describe Notify do ...@@ -207,6 +239,8 @@ describe Notify do
describe 'that are new with a description' do describe 'that are new with a description' do
subject { Notify.new_issue_email(issue_with_description.assignee_id, issue_with_description.id) } subject { Notify.new_issue_email(issue_with_description.assignee_id, issue_with_description.id) }
it_behaves_like 'it should show Gmail Actions View Issue link'
it 'contains the description' do it 'contains the description' do
is_expected.to have_body_text /#{issue_with_description.description}/ is_expected.to have_body_text /#{issue_with_description.description}/
end end
...@@ -217,6 +251,7 @@ describe Notify do ...@@ -217,6 +251,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email' it_behaves_like 'a multiple recipients email'
it_behaves_like 'an answer to an existing thread', 'issue' it_behaves_like 'an answer to an existing thread', 'issue'
it_behaves_like 'it should show Gmail Actions View Issue link'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
...@@ -246,6 +281,7 @@ describe Notify do ...@@ -246,6 +281,7 @@ describe Notify do
subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) } subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) }
it_behaves_like 'an answer to an existing thread', 'issue' it_behaves_like 'an answer to an existing thread', 'issue'
it_behaves_like 'it should show Gmail Actions View Issue link'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
...@@ -269,7 +305,6 @@ describe Notify do ...@@ -269,7 +305,6 @@ describe Notify do
is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/ is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
end end
end end
end end
context 'for merge requests' do context 'for merge requests' do
...@@ -283,6 +318,7 @@ describe Notify do ...@@ -283,6 +318,7 @@ describe Notify do
it_behaves_like 'an assignee email' it_behaves_like 'an assignee email'
it_behaves_like 'an email starting a new thread', 'merge_request' it_behaves_like 'an email starting a new thread', 'merge_request'
it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'has the correct subject' do it 'has the correct subject' do
is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
...@@ -326,6 +362,8 @@ describe Notify do ...@@ -326,6 +362,8 @@ describe Notify do
) )
end end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'contains the description' do it 'contains the description' do
is_expected.to have_body_text /#{merge_request_with_description.description}/ is_expected.to have_body_text /#{merge_request_with_description.description}/
end end
...@@ -336,6 +374,7 @@ describe Notify do ...@@ -336,6 +374,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email' it_behaves_like 'a multiple recipients email'
it_behaves_like 'an answer to an existing thread', 'merge_request' it_behaves_like 'an answer to an existing thread', 'merge_request'
it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
...@@ -365,6 +404,7 @@ describe Notify do ...@@ -365,6 +404,7 @@ describe Notify do
subject { Notify.merge_request_status_email(recipient.id, merge_request.id, status, current_user) } subject { Notify.merge_request_status_email(recipient.id, merge_request.id, status, current_user) }
it_behaves_like 'an answer to an existing thread', 'merge_request' it_behaves_like 'an answer to an existing thread', 'merge_request'
it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
...@@ -394,6 +434,7 @@ describe Notify do ...@@ -394,6 +434,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email' it_behaves_like 'a multiple recipients email'
it_behaves_like 'an answer to an existing thread', 'merge_request' it_behaves_like 'an answer to an existing thread', 'merge_request'
it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'is sent as the merge author' do it 'is sent as the merge author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
...@@ -422,6 +463,7 @@ describe Notify do ...@@ -422,6 +463,7 @@ describe Notify do
subject { Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab") } subject { Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
it_behaves_like 'an email sent from GitLab' it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it 'has the correct subject' do it 'has the correct subject' do
is_expected.to have_subject /Project was moved/ is_expected.to have_subject /Project was moved/
...@@ -443,13 +485,16 @@ describe Notify do ...@@ -443,13 +485,16 @@ describe Notify do
subject { Notify.project_access_granted_email(project_member.id) } subject { Notify.project_access_granted_email(project_member.id) }
it_behaves_like 'an email sent from GitLab' it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it 'has the correct subject' do it 'has the correct subject' do
is_expected.to have_subject /Access to project was granted/ is_expected.to have_subject /Access to project was granted/
end end
it 'contains name of project' do it 'contains name of project' do
is_expected.to have_body_text /#{project.name}/ is_expected.to have_body_text /#{project.name}/
end end
it 'contains new user role' do it 'contains new user role' do
is_expected.to have_body_text /#{project_member.human_access}/ is_expected.to have_body_text /#{project_member.human_access}/
end end
...@@ -464,6 +509,8 @@ describe Notify do ...@@ -464,6 +509,8 @@ describe Notify do
end end
shared_examples 'a note email' do shared_examples 'a note email' do
it_behaves_like 'it should have Gmail Actions links'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(note_author.name) expect(sender.display_name).to eq(note_author.name)
...@@ -488,6 +535,7 @@ describe Notify do ...@@ -488,6 +535,7 @@ describe Notify do
it_behaves_like 'a note email' it_behaves_like 'a note email'
it_behaves_like 'an answer to an existing thread', 'commit' it_behaves_like 'an answer to an existing thread', 'commit'
it_behaves_like 'it should show Gmail Actions View Commit link'
it 'has the correct subject' do it 'has the correct subject' do
is_expected.to have_subject /#{commit.title} \(#{commit.short_id}\)/ is_expected.to have_subject /#{commit.title} \(#{commit.short_id}\)/
...@@ -507,6 +555,7 @@ describe Notify do ...@@ -507,6 +555,7 @@ describe Notify do
it_behaves_like 'a note email' it_behaves_like 'a note email'
it_behaves_like 'an answer to an existing thread', 'merge_request' it_behaves_like 'an answer to an existing thread', 'merge_request'
it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'has the correct subject' do it 'has the correct subject' do
is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
...@@ -526,6 +575,7 @@ describe Notify do ...@@ -526,6 +575,7 @@ describe Notify do
it_behaves_like 'a note email' it_behaves_like 'a note email'
it_behaves_like 'an answer to an existing thread', 'issue' it_behaves_like 'an answer to an existing thread', 'issue'
it_behaves_like 'it should show Gmail Actions View Issue link'
it 'has the correct subject' do it 'has the correct subject' do
is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/ is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
...@@ -546,6 +596,7 @@ describe Notify do ...@@ -546,6 +596,7 @@ describe Notify do
subject { Notify.group_access_granted_email(membership.id) } subject { Notify.group_access_granted_email(membership.id) }
it_behaves_like 'an email sent from GitLab' it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it 'has the correct subject' do it 'has the correct subject' do
is_expected.to have_subject /Access to group was granted/ is_expected.to have_subject /Access to group was granted/
...@@ -593,6 +644,8 @@ describe Notify do ...@@ -593,6 +644,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :create) } subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :create) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name) expect(sender.display_name).to eq(user.name)
...@@ -619,6 +672,8 @@ describe Notify do ...@@ -619,6 +672,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :create) } subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name) expect(sender.display_name).to eq(user.name)
...@@ -644,6 +699,8 @@ describe Notify do ...@@ -644,6 +699,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :delete) } subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :delete) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name) expect(sender.display_name).to eq(user.name)
...@@ -665,6 +722,8 @@ describe Notify do ...@@ -665,6 +722,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) } subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name) expect(sender.display_name).to eq(user.name)
...@@ -690,6 +749,8 @@ describe Notify do ...@@ -690,6 +749,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, send_from_committer_email: send_from_committer_email) } subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, send_from_committer_email: send_from_committer_email) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name) expect(sender.display_name).to eq(user.name)
...@@ -793,6 +854,8 @@ describe Notify do ...@@ -793,6 +854,8 @@ describe Notify do
subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare) } subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare) }
it_behaves_like 'it should show Gmail Actions View Commit link'
it 'is sent as the author' do it 'is sent as the author' do
sender = subject.header[:from].addrs[0] sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name) expect(sender.display_name).to eq(user.name)
......
...@@ -44,13 +44,10 @@ describe Ci::MailService do ...@@ -44,13 +44,10 @@ describe Ci::MailService do
end end
it do it do
should_email("git@example.com") perform_enqueued_jobs do
mail.execute(build) expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
end expect(ActionMailer::Base.deliveries.last.to).to eq(["git@example.com"])
end
def should_email(email)
expect(Ci::Notify).to receive(:build_fail_email).with(build.id, email)
expect(Ci::Notify).not_to receive(:build_success_email).with(build.id, email)
end end
end end
...@@ -67,13 +64,10 @@ describe Ci::MailService do ...@@ -67,13 +64,10 @@ describe Ci::MailService do
end end
it do it do
should_email("git@example.com") perform_enqueued_jobs do
mail.execute(build) expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
end expect(ActionMailer::Base.deliveries.last.to).to eq(["git@example.com"])
end
def should_email(email)
expect(Ci::Notify).to receive(:build_success_email).with(build.id, email)
expect(Ci::Notify).not_to receive(:build_fail_email).with(build.id, email)
end end
end end
...@@ -95,14 +89,12 @@ describe Ci::MailService do ...@@ -95,14 +89,12 @@ describe Ci::MailService do
end end
it do it do
should_email("git@example.com") perform_enqueued_jobs do
should_email("jeroen@example.com") expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(2)
mail.execute(build) expect(
end ActionMailer::Base.deliveries.map(&:to).flatten
).to include("git@example.com", "jeroen@example.com")
def should_email(email) end
expect(Ci::Notify).to receive(:build_success_email).with(build.id, email)
expect(Ci::Notify).not_to receive(:build_fail_email).with(build.id, email)
end end
end end
...@@ -124,14 +116,11 @@ describe Ci::MailService do ...@@ -124,14 +116,11 @@ describe Ci::MailService do
end end
it do it do
should_email(commit.git_author_email) perform_enqueued_jobs do
should_email("jeroen@example.com") expect do
mail.execute(build) if mail.can_execute?(build) mail.execute(build) if mail.can_execute?(build)
end end.to_not change{ ActionMailer::Base.deliveries.size }
end
def should_email(email)
expect(Ci::Notify).not_to receive(:build_success_email).with(build.id, email)
expect(Ci::Notify).not_to receive(:build_fail_email).with(build.id, email)
end end
end end
...@@ -177,14 +166,11 @@ describe Ci::MailService do ...@@ -177,14 +166,11 @@ describe Ci::MailService do
it do it do
Ci::Build.retry(build) Ci::Build.retry(build)
should_email(commit.git_author_email) perform_enqueued_jobs do
should_email("jeroen@example.com") expect do
mail.execute(build) if mail.can_execute?(build) mail.execute(build) if mail.can_execute?(build)
end end.to_not change{ ActionMailer::Base.deliveries.size }
end
def should_email(email)
expect(Ci::Notify).not_to receive(:build_success_email).with(build.id, email)
expect(Ci::Notify).not_to receive(:build_fail_email).with(build.id, email)
end end
end end
end end
......
require 'spec_helper'
describe Milestone, "StripAttribute" do
let(:milestone) { create(:milestone) }
describe ".strip_attributes" do
it { expect(Milestone).to respond_to(:strip_attributes) }
it { expect(Milestone.strip_attrs).to include(:title) }
end
describe "#strip_attributes" do
before do
milestone.title = ' 8.3 '
milestone.valid?
end
it { expect(milestone.title).to eq('8.3') }
end
end
...@@ -203,9 +203,9 @@ describe JiraService do ...@@ -203,9 +203,9 @@ describe JiraService do
end end
it 'should be prepopulated with the settings' do it 'should be prepopulated with the settings' do
expect(@service.properties[:project_url]).to eq('http://jira.sample/projects/project_a') expect(@service.properties["project_url"]).to eq('http://jira.sample/projects/project_a')
expect(@service.properties[:issues_url]).to eq("http://jira.sample/issues/:id") expect(@service.properties["issues_url"]).to eq("http://jira.sample/issues/:id")
expect(@service.properties[:new_issue_url]).to eq("http://jira.sample/projects/project_a/issues/new") expect(@service.properties["new_issue_url"]).to eq("http://jira.sample/projects/project_a/issues/new")
end end
end end
end end
......
...@@ -14,7 +14,9 @@ describe Issues::CloseService do ...@@ -14,7 +14,9 @@ describe Issues::CloseService do
describe :execute do describe :execute do
context "valid params" do context "valid params" do
before do before do
@issue = Issues::CloseService.new(project, user, {}).execute(issue) perform_enqueued_jobs do
@issue = Issues::CloseService.new(project, user, {}).execute(issue)
end
end end
it { expect(@issue).to be_valid } it { expect(@issue).to be_valid }
......
...@@ -36,7 +36,10 @@ describe Issues::UpdateService do ...@@ -36,7 +36,10 @@ describe Issues::UpdateService do
label_ids: [label.id] label_ids: [label.id]
} }
@issue = Issues::UpdateService.new(project, user, opts).execute(issue) perform_enqueued_jobs do
@issue = Issues::UpdateService.new(project, user, opts).execute(issue)
end
@issue.reload @issue.reload
end end
......
...@@ -18,7 +18,9 @@ describe MergeRequests::CloseService do ...@@ -18,7 +18,9 @@ describe MergeRequests::CloseService do
before do before do
allow(service).to receive(:execute_hooks) allow(service).to receive(:execute_hooks)
@merge_request = service.execute(merge_request) perform_enqueued_jobs do
@merge_request = service.execute(merge_request)
end
end end
it { expect(@merge_request).to be_valid } it { expect(@merge_request).to be_valid }
......
...@@ -17,8 +17,9 @@ describe MergeRequests::MergeService do ...@@ -17,8 +17,9 @@ describe MergeRequests::MergeService do
before do before do
allow(service).to receive(:execute_hooks) allow(service).to receive(:execute_hooks)
perform_enqueued_jobs do
service.execute(merge_request, 'Awesome message') service.execute(merge_request, 'Awesome message')
end
end end
it { expect(merge_request).to be_valid } it { expect(merge_request).to be_valid }
......
...@@ -19,7 +19,9 @@ describe MergeRequests::ReopenService do ...@@ -19,7 +19,9 @@ describe MergeRequests::ReopenService do
allow(service).to receive(:execute_hooks) allow(service).to receive(:execute_hooks)
merge_request.state = :closed merge_request.state = :closed
service.execute(merge_request) perform_enqueued_jobs do
service.execute(merge_request)
end
end end
it { expect(merge_request).to be_valid } it { expect(merge_request).to be_valid }
......
...@@ -42,8 +42,10 @@ describe MergeRequests::UpdateService do ...@@ -42,8 +42,10 @@ describe MergeRequests::UpdateService do
before do before do
allow(service).to receive(:execute_hooks) allow(service).to receive(:execute_hooks)
@merge_request = service.execute(merge_request) perform_enqueued_jobs do
@merge_request.reload @merge_request = service.execute(merge_request)
@merge_request.reload
end
end end
it { expect(@merge_request).to be_valid } it { expect(@merge_request).to be_valid }
......
...@@ -3,6 +3,12 @@ require 'spec_helper' ...@@ -3,6 +3,12 @@ require 'spec_helper'
describe NotificationService do describe NotificationService do
let(:notification) { NotificationService.new } let(:notification) { NotificationService.new }
around(:each) do |example|
perform_enqueued_jobs do
example.run
end
end
describe 'Keys' do describe 'Keys' do
describe :new_key do describe :new_key do
let!(:key) { create(:personal_key) } let!(:key) { create(:personal_key) }
...@@ -10,8 +16,7 @@ describe NotificationService do ...@@ -10,8 +16,7 @@ describe NotificationService do
it { expect(notification.new_key(key)).to be_truthy } it { expect(notification.new_key(key)).to be_truthy }
it 'should sent email to key owner' do it 'should sent email to key owner' do
expect(Notify).to receive(:new_ssh_key_email).with(key.id) expect{ notification.new_key(key) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
notification.new_key(key)
end end
end end
end end
...@@ -23,8 +28,7 @@ describe NotificationService do ...@@ -23,8 +28,7 @@ describe NotificationService do
it { expect(notification.new_email(email)).to be_truthy } it { expect(notification.new_email(email)).to be_truthy }
it 'should send email to email owner' do it 'should send email to email owner' do
expect(Notify).to receive(:new_email_email).with(email.id) expect{ notification.new_email(email) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
notification.new_email(email)
end end
end end
end end
...@@ -47,18 +51,20 @@ describe NotificationService do ...@@ -47,18 +51,20 @@ describe NotificationService do
it do it do
add_users_with_subscription(note.project, issue) add_users_with_subscription(note.project, issue)
should_email(@u_watcher.id) ActionMailer::Base.deliveries.clear
should_email(note.noteable.author_id)
should_email(note.noteable.assignee_id)
should_email(@u_mentioned.id)
should_email(@subscriber.id)
should_not_email(note.author_id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
should_not_email(@unsubscriber.id)
should_not_email(@u_outsider_mentioned)
notification.new_note(note) notification.new_note(note)
should_email(@u_watcher)
should_email(note.noteable.author)
should_email(note.noteable.assignee)
should_email(@u_mentioned)
should_email(@subscriber)
should_not_email(note.author)
should_not_email(@u_participating)
should_not_email(@u_disabled)
should_not_email(@unsubscriber)
should_not_email(@u_outsider_mentioned)
end end
it 'filters out "mentioned in" notes' do it 'filters out "mentioned in" notes' do
...@@ -82,26 +88,20 @@ describe NotificationService do ...@@ -82,26 +88,20 @@ describe NotificationService do
group_member = note.project.group.group_members.find_by_user_id(@u_watcher.id) group_member = note.project.group.group_members.find_by_user_id(@u_watcher.id)
group_member.notification_level = Notification::N_GLOBAL group_member.notification_level = Notification::N_GLOBAL
group_member.save group_member.save
ActionMailer::Base.deliveries.clear
end end
it do it do
should_email(note.noteable.author_id)
should_email(note.noteable.assignee_id)
should_email(@u_mentioned.id)
should_not_email(@u_watcher.id)
should_not_email(note.author_id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.new_note(note) notification.new_note(note)
end
end
def should_email(user_id) should_email(note.noteable.author)
expect(Notify).to receive(:note_issue_email).with(user_id, note.id) should_email(note.noteable.assignee)
end should_email(@u_mentioned)
should_not_email(@u_watcher)
def should_not_email(user_id) should_not_email(note.author)
expect(Notify).not_to receive(:note_issue_email).with(user_id, note.id) should_not_email(@u_participating)
should_not_email(@u_disabled)
end
end end
end end
...@@ -113,24 +113,26 @@ describe NotificationService do ...@@ -113,24 +113,26 @@ describe NotificationService do
before do before do
build_team(note.project) build_team(note.project)
ActionMailer::Base.deliveries.clear
end end
describe :new_note do describe :new_note do
it do it do
notification.new_note(note)
# Notify all team members # Notify all team members
note.project.team.members.each do |member| note.project.team.members.each do |member|
# User with disabled notification should not be notified # User with disabled notification should not be notified
next if member.id == @u_disabled.id next if member.id == @u_disabled.id
should_email(member.id) should_email(member)
end end
should_email(note.noteable.author_id)
should_email(note.noteable.assignee_id)
should_not_email(note.author_id) should_email(note.noteable.author)
should_not_email(@u_mentioned.id) should_email(note.noteable.assignee)
should_not_email(@u_disabled.id) should_not_email(note.author)
should_not_email(@u_not_mentioned.id) should_email(@u_mentioned)
notification.new_note(note) should_not_email(@u_disabled)
should_email(@u_not_mentioned)
end end
it 'filters out "mentioned in" notes' do it 'filters out "mentioned in" notes' do
...@@ -140,14 +142,6 @@ describe NotificationService do ...@@ -140,14 +142,6 @@ describe NotificationService do
notification.new_note(mentioned_note) notification.new_note(mentioned_note)
end end
end end
def should_email(user_id)
expect(Notify).to receive(:note_issue_email).with(user_id, note.id)
end
def should_not_email(user_id)
expect(Notify).not_to receive(:note_issue_email).with(user_id, note.id)
end
end end
context 'commit note' do context 'commit note' do
...@@ -156,43 +150,38 @@ describe NotificationService do ...@@ -156,43 +150,38 @@ describe NotificationService do
before do before do
build_team(note.project) build_team(note.project)
ActionMailer::Base.deliveries.clear
allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer) allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer)
end end
describe :new_note do describe :new_note, :perform_enqueued_jobs do
it do it do
should_email(@u_committer.id, note)
should_email(@u_watcher.id, note)
should_not_email(@u_mentioned.id, note)
should_not_email(note.author_id, note)
should_not_email(@u_participating.id, note)
should_not_email(@u_disabled.id, note)
notification.new_note(note) notification.new_note(note)
should_email(@u_committer)
should_email(@u_watcher)
should_not_email(@u_mentioned)
should_not_email(note.author)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
it do it do
note.update_attribute(:note, '@mention referenced') note.update_attribute(:note, '@mention referenced')
should_email(@u_committer.id, note)
should_email(@u_watcher.id, note)
should_email(@u_mentioned.id, note)
should_not_email(note.author_id, note)
should_not_email(@u_participating.id, note)
should_not_email(@u_disabled.id, note)
notification.new_note(note) notification.new_note(note)
should_email(@u_committer)
should_email(@u_watcher)
should_email(@u_mentioned)
should_not_email(note.author)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
it do it do
@u_committer.update_attributes(notification_level: Notification::N_MENTION) @u_committer.update_attributes(notification_level: Notification::N_MENTION)
should_not_email(@u_committer.id, note)
notification.new_note(note) notification.new_note(note)
end should_not_email(@u_committer)
def should_email(user_id, n)
expect(Notify).to receive(:note_commit_email).with(user_id, n.id)
end
def should_not_email(user_id, n)
expect(Notify).not_to receive(:note_commit_email).with(user_id, n.id)
end end
end end
end end
...@@ -205,99 +194,69 @@ describe NotificationService do ...@@ -205,99 +194,69 @@ describe NotificationService do
before do before do
build_team(issue.project) build_team(issue.project)
add_users_with_subscription(issue.project, issue) add_users_with_subscription(issue.project, issue)
ActionMailer::Base.deliveries.clear
end end
describe :new_issue do describe :new_issue do
it do it do
should_email(issue.assignee_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_not_email(@u_mentioned.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.new_issue(issue, @u_disabled) notification.new_issue(issue, @u_disabled)
should_email(issue.assignee)
should_email(@u_watcher)
should_email(@u_participant_mentioned)
should_not_email(@u_mentioned)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
it do it do
issue.assignee.update_attributes(notification_level: Notification::N_MENTION) issue.assignee.update_attributes(notification_level: Notification::N_MENTION)
should_not_email(issue.assignee_id)
notification.new_issue(issue, @u_disabled) notification.new_issue(issue, @u_disabled)
end
def should_email(user_id)
expect(Notify).to receive(:new_issue_email).with(user_id, issue.id)
end
def should_not_email(user_id) should_not_email(issue.assignee)
expect(Notify).not_to receive(:new_issue_email).with(user_id, issue.id)
end end
end end
describe :reassigned_issue do describe :reassigned_issue do
it 'should email new assignee' do it 'should email new assignee' do
should_email(issue.assignee_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_email(@subscriber.id)
should_not_email(@unsubscriber.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.reassigned_issue(issue, @u_disabled) notification.reassigned_issue(issue, @u_disabled)
end
def should_email(user_id)
expect(Notify).to receive(:reassigned_issue_email).with(user_id, issue.id, nil, @u_disabled.id)
end
def should_not_email(user_id) should_email(issue.assignee)
expect(Notify).not_to receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id) should_email(@u_watcher)
should_email(@u_participant_mentioned)
should_email(@subscriber)
should_not_email(@unsubscriber)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
end end
describe :close_issue do describe :close_issue do
it 'should sent email to issue assignee and issue author' do it 'should sent email to issue assignee and issue author' do
should_email(issue.assignee_id)
should_email(issue.author_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_email(@subscriber.id)
should_not_email(@unsubscriber.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.close_issue(issue, @u_disabled) notification.close_issue(issue, @u_disabled)
end
def should_email(user_id) should_email(issue.assignee)
expect(Notify).to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) should_email(issue.author)
end should_email(@u_watcher)
should_email(@u_participant_mentioned)
def should_not_email(user_id) should_email(@subscriber)
expect(Notify).not_to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) should_not_email(@unsubscriber)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
end end
describe :reopen_issue do describe :reopen_issue do
it 'should send email to issue assignee and issue author' do it 'should send email to issue assignee and issue author' do
should_email(issue.assignee_id)
should_email(issue.author_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_email(@subscriber.id)
should_not_email(@unsubscriber.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.reopen_issue(issue, @u_disabled) notification.reopen_issue(issue, @u_disabled)
end
def should_email(user_id)
expect(Notify).to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id)
end
def should_not_email(user_id) should_email(issue.assignee)
expect(Notify).not_to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id) should_email(issue.author)
should_email(@u_watcher)
should_email(@u_participant_mentioned)
should_email(@subscriber)
should_not_email(@unsubscriber)
should_not_email(@u_participating)
end end
end end
end end
...@@ -309,108 +268,74 @@ describe NotificationService do ...@@ -309,108 +268,74 @@ describe NotificationService do
before do before do
build_team(merge_request.target_project) build_team(merge_request.target_project)
add_users_with_subscription(merge_request.target_project, merge_request) add_users_with_subscription(merge_request.target_project, merge_request)
ActionMailer::Base.deliveries.clear
end end
describe :new_merge_request do describe :new_merge_request do
it do it do
should_email(merge_request.assignee_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.new_merge_request(merge_request, @u_disabled) notification.new_merge_request(merge_request, @u_disabled)
end
def should_email(user_id) should_email(merge_request.assignee)
expect(Notify).to receive(:new_merge_request_email).with(user_id, merge_request.id) should_email(@u_watcher)
end should_email(@u_participant_mentioned)
should_not_email(@u_participating)
def should_not_email(user_id) should_not_email(@u_disabled)
expect(Notify).not_to receive(:new_merge_request_email).with(user_id, merge_request.id)
end end
end end
describe :reassigned_merge_request do describe :reassigned_merge_request do
it do it do
should_email(merge_request.assignee_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_email(@subscriber.id)
should_not_email(@unsubscriber.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.reassigned_merge_request(merge_request, merge_request.author) notification.reassigned_merge_request(merge_request, merge_request.author)
end
def should_email(user_id)
expect(Notify).to receive(:reassigned_merge_request_email).with(user_id, merge_request.id, nil, merge_request.author_id)
end
def should_not_email(user_id) should_email(merge_request.assignee)
expect(Notify).not_to receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id, merge_request.author_id) should_email(@u_watcher)
should_email(@u_participant_mentioned)
should_email(@subscriber)
should_not_email(@unsubscriber)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
end end
describe :closed_merge_request do describe :closed_merge_request do
it do it do
should_email(merge_request.assignee_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_email(@subscriber.id)
should_not_email(@unsubscriber.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.close_mr(merge_request, @u_disabled) notification.close_mr(merge_request, @u_disabled)
end
def should_email(user_id)
expect(Notify).to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
end
def should_not_email(user_id) should_email(merge_request.assignee)
expect(Notify).not_to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) should_email(@u_watcher)
should_email(@u_participant_mentioned)
should_email(@subscriber)
should_not_email(@unsubscriber)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
end end
describe :merged_merge_request do describe :merged_merge_request do
it do it do
should_email(merge_request.assignee_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_email(@subscriber.id)
should_not_email(@unsubscriber.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.merge_mr(merge_request, @u_disabled) notification.merge_mr(merge_request, @u_disabled)
end
def should_email(user_id)
expect(Notify).to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
end
def should_not_email(user_id) should_email(merge_request.assignee)
expect(Notify).not_to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) should_email(@u_watcher)
should_email(@u_participant_mentioned)
should_email(@subscriber)
should_not_email(@unsubscriber)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
end end
describe :reopen_merge_request do describe :reopen_merge_request do
it do it do
should_email(merge_request.assignee_id)
should_email(@u_watcher.id)
should_email(@u_participant_mentioned.id)
should_email(@subscriber.id)
should_not_email(@unsubscriber.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.reopen_mr(merge_request, @u_disabled) notification.reopen_mr(merge_request, @u_disabled)
end
def should_email(user_id) should_email(merge_request.assignee)
expect(Notify).to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id) should_email(@u_watcher)
end should_email(@u_participant_mentioned)
should_email(@subscriber)
def should_not_email(user_id) should_not_email(@unsubscriber)
expect(Notify).not_to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id) should_not_email(@u_participating)
should_not_email(@u_disabled)
end end
end end
end end
...@@ -420,22 +345,16 @@ describe NotificationService do ...@@ -420,22 +345,16 @@ describe NotificationService do
before do before do
build_team(project) build_team(project)
ActionMailer::Base.deliveries.clear
end end
describe :project_was_moved do describe :project_was_moved do
it do it do
should_email(@u_watcher.id)
should_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.project_was_moved(project, "gitlab/gitlab") notification.project_was_moved(project, "gitlab/gitlab")
end
def should_email(user_id)
expect(Notify).to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab")
end
def should_not_email(user_id) should_email(@u_watcher)
expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab") should_email(@u_participating)
should_not_email(@u_disabled)
end end
end end
end end
...@@ -469,4 +388,18 @@ describe NotificationService do ...@@ -469,4 +388,18 @@ describe NotificationService do
issuable.subscriptions.create(user: @subscriber, subscribed: true) issuable.subscriptions.create(user: @subscriber, subscribed: true)
issuable.subscriptions.create(user: @unsubscriber, subscribed: false) issuable.subscriptions.create(user: @unsubscriber, subscribed: false)
end end
def sent_to_user?(user)
ActionMailer::Base.deliveries.any? do |message|
message.to.include?(user.email)
end
end
def should_email(user)
expect(sent_to_user?(user)).to be_truthy
end
def should_not_email(user)
expect(sent_to_user?(user)).to be_falsey
end
end end
...@@ -31,6 +31,7 @@ RSpec.configure do |config| ...@@ -31,6 +31,7 @@ RSpec.configure do |config|
config.include StubConfiguration config.include StubConfiguration
config.include RelativeUrl, type: feature config.include RelativeUrl, type: feature
config.include TestEnv config.include TestEnv
config.include ActiveJob::TestHelper
config.include StubGitlabCalls config.include StubGitlabCalls
config.include StubGitlabData config.include StubGitlabData
config.include BenchmarkMatchers, benchmark: true config.include BenchmarkMatchers, benchmark: true
......
...@@ -21,12 +21,14 @@ describe EmailReceiverWorker do ...@@ -21,12 +21,14 @@ describe EmailReceiverWorker do
end end
it "sends out a rejection email" do it "sends out a rejection email" do
described_class.new.perform(raw_message) perform_enqueued_jobs do
described_class.new.perform(raw_message)
email = ActionMailer::Base.deliveries.last
expect(email).not_to be_nil email = ActionMailer::Base.deliveries.last
expect(email.to).to eq(["jake@adventuretime.ooo"]) expect(email).not_to be_nil
expect(email.subject).to include("Rejected") expect(email.to).to eq(["jake@adventuretime.ooo"])
expect(email.subject).to include("Rejected")
end
end end
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