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:
Lint/RescueException:
Description: 'Avoid rescuing the Exception class.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues'
Enabled: false
Enabled: true
Lint/ShadowingOuterLocalVariable:
Description: >-
......
......@@ -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)
- 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
- Forcefully update builds that didn't want to update with state machine
......@@ -22,7 +33,6 @@ v 8.2.0
- Expose build artifacts path as config option
- Fix grouping of contributors by email in graph.
- 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 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)
......
......@@ -47,10 +47,10 @@ Please send a merge request with a tested solution or a merge request with a fai
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. **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)
* 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
## Merge requests
......
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
# See https://groups.google.com/forum/#!topic/rubyonrails-security/doAVp0YaTqY
......@@ -16,7 +20,7 @@ gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries
gem 'devise', '~> 3.5.2'
gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.1.3'
gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.2.2'
gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-facebook', '~> 3.0.0'
......@@ -29,7 +33,7 @@ gem 'omniauth-shibboleth', '~> 1.2.0'
gem 'omniauth-twitter', '~> 1.2.0'
gem 'omniauth_crowd'
gem 'gssapi', group: :kerberos
gem 'rack-oauth2', '~> 1.0.5'
gem 'rack-oauth2', '~> 1.2.1'
# Two-factor authentication
gem 'devise-two-factor', '~> 2.0.0'
......@@ -97,9 +101,10 @@ gem 'redcarpet', '~> 3.3.3'
gem 'RedCloth', '~> 4.2.9'
gem 'rdoc', '~>3.6'
gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~>0.3.6'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.2'
gem 'net-ssh', '~> 3.0.1'
# Diffs
gem 'diffy', '~> 3.0.3'
......@@ -128,7 +133,7 @@ gem "httparty", '~> 0.13.3'
# Colored output to console
gem "colored", '~> 1.2'
gem "colorize", '~> 0.5.8'
gem "colorize", '~> 0.7.0'
# GitLab settings
gem 'settingslogic', '~> 2.0.9'
......@@ -156,7 +161,7 @@ gem "gemnasium-gitlab-service", "~> 0.2"
gem "slack-notifier", "~> 1.2.0"
# Asana integration
gem 'asana', '~> 0.0.6'
gem 'asana', '~> 0.4.0'
# FogBugz integration
gem 'ruby-fogbugz', '~> 0.2.1'
......@@ -189,13 +194,13 @@ gem "sass-rails", '~> 4.0.5'
gem "coffee-rails", '~> 4.1.0'
gem "uglifier", '~> 2.7.2'
gem 'turbolinks', '~> 2.5.0'
gem 'jquery-turbolinks', '~> 2.0.1'
gem 'jquery-turbolinks', '~> 2.1.0'
gem 'addressable', '~> 2.3.8'
gem 'bootstrap-sass', '~> 3.0'
gem 'font-awesome-rails', '~> 4.2'
gem 'gitlab_emoji', '~> 0.1'
gem 'gon', '~> 5.0.0'
gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 3.1.3'
gem 'jquery-scrollto-rails', '~> 1.4.3'
......@@ -218,6 +223,7 @@ group :development do
gem 'rerun', '~> 0.10.0'
gem 'bullet', require: false
gem 'rblineprof', platform: :mri, require: false
gem 'web-console', '~> 2.0'
# Better errors handler
gem 'better_errors', '~> 1.0.1'
......@@ -274,7 +280,7 @@ group :test do
gem 'shoulda-matchers', '~> 2.8.0', require: false
gem 'email_spec', '~> 1.6.0'
gem 'webmock', '~> 1.21.0'
gem 'test_after_commit', '~> 0.2.2'
gem 'test_after_commit', '~> 0.4.2'
gem 'sham_rack'
end
......
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (2.3.1)
CFPropertyList (2.3.2)
RedCloth (4.2.9)
ace-rails-ap (2.0.1)
actionmailer (4.1.14)
actionpack (= 4.1.14)
actionview (= 4.1.14)
actionmailer (4.2.4)
actionpack (= 4.2.4)
actionview (= 4.2.4)
activejob (= 4.2.4)
mail (~> 2.5, >= 2.5.4)
actionpack (4.1.14)
actionview (= 4.1.14)
activesupport (= 4.1.14)
rack (~> 1.5.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.4)
actionview (= 4.2.4)
activesupport (= 4.2.4)
rack (~> 1.6)
rack-test (~> 0.6.2)
actionview (4.1.14)
activesupport (= 4.1.14)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.4)
activesupport (= 4.2.4)
builder (~> 3.1)
erubis (~> 2.7.0)
activemodel (4.1.14)
activesupport (= 4.1.14)
rails-dom-testing (~> 1.0, >= 1.0.5)
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)
activerecord (4.1.14)
activemodel (= 4.1.14)
activesupport (= 4.1.14)
arel (~> 5.0.0)
activerecord (4.2.4)
activemodel (= 4.2.4)
activesupport (= 4.2.4)
arel (~> 6.0)
activerecord-deprecated_finders (1.0.4)
activerecord-session_store (0.1.1)
activerecord-session_store (0.1.2)
actionpack (>= 4.0.0, < 5)
activerecord (>= 4.0.0, < 5)
railties (>= 4.0.0, < 5)
activeresource (4.0.0)
activemodel (~> 4.0)
activesupport (~> 4.0)
rails-observers (~> 0.1.1)
activesupport (4.1.14)
i18n (~> 0.6, >= 0.6.9)
activesupport (4.2.4)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
acts-as-taggable-on (3.5.0)
activerecord (>= 3.2, < 5)
addressable (2.3.8)
after_commit_queue (1.1.0)
rails (>= 3.0)
after_commit_queue (1.3.0)
activerecord (>= 3.0)
annotate (2.6.10)
activerecord (>= 3.2, <= 4.3)
rake (~> 10.4)
arel (5.0.1.20140414130214)
asana (0.0.6)
activeresource (>= 3.2.3)
asciidoctor (1.5.2)
arel (6.0.3)
asana (0.4.0)
faraday (~> 0.9)
faraday_middleware (~> 0.9)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
asciidoctor (1.5.3)
ast (2.1.0)
astrolabe (1.3.1)
parser (~> 2.2)
attr_encrypted (1.3.4)
encryptor (>= 1.3.0)
attr_required (1.0.0)
autoprefixer-rails (5.2.1.2)
autoprefixer-rails (6.1.1)
execjs
json
awesome_print (1.2.0)
......@@ -85,15 +93,15 @@ GEM
ruby_parser (~> 3.5.0)
sass (~> 3.0)
terminal-table (~> 1.4)
browser (1.0.0)
browser (1.0.1)
builder (3.2.2)
bullet (4.14.9)
bullet (4.14.10)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.9.0)
bundler-audit (0.4.0)
bundler (~> 1.2)
thor (~> 0.18)
byebug (6.0.2)
byebug (8.2.0)
cal-heatmap-rails (0.0.1)
capybara (2.4.4)
mime-types (>= 1.16)
......@@ -108,10 +116,25 @@ GEM
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
json (>= 1.7)
celluloid (0.16.0)
timers (~> 4.0.0)
celluloid (0.17.2)
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)
chunky_png (1.3.4)
chunky_png (1.3.5)
cliver (0.3.2)
coderay (1.1.0)
coercible (1.0.0)
......@@ -122,19 +145,19 @@ GEM
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.9.1.1)
colored (1.2)
colorize (0.5.8)
coffee-script-source (1.10.0)
colorize (0.7.7)
connection_pool (2.2.0)
coveralls (0.8.2)
coveralls (0.8.9)
json (~> 1.8)
rest-client (>= 1.6.8, < 2)
simplecov (~> 0.10.0)
term-ansicolor (~> 1.3)
thor (~> 0.19.1)
tins (~> 1.6.0)
crack (0.4.2)
safe_yaml (~> 1.0.0)
creole (0.3.8)
creole (0.5.0)
d3_rails (3.5.6)
railties (>= 3.1.0)
daemons (1.2.3)
......@@ -154,7 +177,7 @@ GEM
warden (~> 1.2.3)
devise-async (0.9.0)
devise (~> 3.2)
devise-two-factor (2.0.0)
devise-two-factor (2.0.1)
activesupport
attr_encrypted (~> 1.3.2)
devise (~> 3.5.0)
......@@ -163,19 +186,17 @@ GEM
diff-lcs (1.2.5)
diffy (3.0.7)
docile (1.1.5)
domain_name (0.5.24)
domain_name (0.5.25)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (2.1.4)
doorkeeper (2.2.2)
railties (>= 3.2)
dropzonejs-rails (0.7.1)
dropzonejs-rails (0.7.2)
rails (> 3.1)
email_reply_parser (0.5.8)
email_spec (1.6.0)
launchy (~> 2.1)
mail (~> 2.2)
encryptor (1.3.0)
enumerize (0.7.0)
activesupport (>= 3.2)
equalizer (0.0.11)
erubis (2.7.0)
escape_utils (1.1.0)
......@@ -192,6 +213,9 @@ GEM
multipart-post (>= 1.2, < 3)
faraday_middleware (0.10.0)
faraday (>= 0.7.4, < 0.10)
faraday_middleware-multi_json (0.0.6)
faraday_middleware
multi_json
fastercsv (1.5.5)
ffaker (2.0.0)
ffi (1.9.10)
......@@ -203,7 +227,7 @@ GEM
flog (4.3.2)
ruby_parser (~> 3.1, > 3.1.0)
sexp_processor (~> 4.4)
flowdock (0.7.0)
flowdock (0.7.1)
httparty (~> 0.7)
multi_json
fog (1.25.0)
......@@ -225,13 +249,10 @@ GEM
fog-core (~> 1.22)
fog-json
inflecto (~> 0.0.2)
fog-core (1.32.1)
fog-core (1.35.0)
builder
excon (~> 0.45)
formatador (~> 0.2)
mime-types
net-scp (~> 1.1)
net-ssh (>= 2.1.3)
fog-json (1.0.2)
fog-core (~> 1.0)
multi_json (~> 1.10)
......@@ -243,10 +264,10 @@ GEM
fog-core (>= 1.21.0)
fog-json
fog-xml (>= 0.0.1)
fog-sakuracloud (1.0.1)
fog-sakuracloud (1.4.0)
fog-core
fog-json
fog-softlayer (0.4.7)
fog-softlayer (1.0.2)
fog-core
fog-json
fog-terremark (0.1.0)
......@@ -261,7 +282,7 @@ GEM
fog-xml (0.1.2)
fog-core
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)
foreman (0.78.0)
thor (~> 0.19.1)
......@@ -271,11 +292,11 @@ GEM
ruby-progressbar (~> 1.4)
gemnasium-gitlab-service (0.2.6)
rugged (~> 0.21)
gemojione (2.0.1)
gemojione (2.1.0)
json
get_process_mem (0.2.0)
gherkin-ruby (0.3.2)
github-linguist (4.7.0)
github-linguist (4.7.2)
charlock_holmes (~> 0.7.3)
escape_utils (~> 1.1.0)
mime-types (>= 1.19)
......@@ -291,8 +312,8 @@ GEM
mime-types (~> 1.15)
posix-spawn (~> 0.3)
gitlab-license (0.0.4)
gitlab_emoji (0.1.1)
gemojione (~> 2.0)
gitlab_emoji (0.2.0)
gemojione (~> 2.1)
gitlab_git (7.2.20)
activesupport (~> 4.0)
charlock_holmes (~> 0.7.3)
......@@ -304,6 +325,8 @@ GEM
omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.3)
globalid (0.3.6)
activesupport (>= 4.1.0)
gollum-grit_adapter (1.0.0)
gitlab-grit (~> 2.7, >= 2.7.1)
gollum-lib (4.0.3)
......@@ -313,9 +336,11 @@ GEM
rouge (~> 1.10.1)
sanitize (~> 2.1.0)
stringex (~> 2.5.1)
gon (5.0.4)
actionpack (>= 2.3.0)
gon (6.0.1)
actionpack (>= 3.0)
json
multi_json
request_store (>= 1.0)
grape (0.13.0)
activesupport
builder
......@@ -339,7 +364,7 @@ GEM
haml (>= 4.0.6, < 5.0)
html2haml (>= 1.0.1)
railties (>= 4.0.1)
hashie (3.4.2)
hashie (3.4.3)
highline (1.6.21)
hike (1.2.3)
hipchat (1.5.2)
......@@ -357,40 +382,42 @@ GEM
http-cookie (1.0.2)
domain_name (~> 0.5)
http_parser.rb (0.5.3)
httparty (0.13.5)
httparty (0.13.7)
json (~> 1.8)
multi_xml (>= 0.5.2)
httpclient (2.6.0.1)
httpclient (2.7.0.1)
i18n (0.7.0)
ice_cube (0.11.1)
ice_nine (0.11.1)
inflecto (0.0.2)
ipaddress (0.8.0)
jquery-atwho-rails (1.3.2)
jquery-rails (3.1.3)
jquery-rails (3.1.4)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
jquery-scrollto-rails (1.4.3)
railties (> 3.1, < 5.0)
jquery-turbolinks (2.0.2)
jquery-turbolinks (2.1.0)
railties (>= 3.1.0)
turbolinks
jquery-ui-rails (4.2.1)
railties (>= 3.2.16)
json (1.8.3)
jwt (1.5.1)
jwt (1.5.2)
kaminari (0.16.3)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.9.3)
kgio (2.10.0)
launchy (2.4.3)
addressable (~> 2.3)
letter_opener (1.1.2)
launchy (~> 2.2)
listen (2.10.1)
celluloid (~> 0.16.0)
listen (2.9.0)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
loofah (2.0.3)
nokogiri (>= 1.5.9)
macaddr (1.7.1)
systemu (~> 2.6.2)
mail (2.6.3)
......@@ -407,16 +434,14 @@ GEM
multipart-post (2.0.0)
mysql2 (0.3.20)
nested_form (0.3.2)
net-ldap (0.11)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (2.9.2)
netrc (0.10.3)
net-ldap (0.12.1)
net-ssh (3.0.1)
netrc (0.11.0)
newrelic-grape (2.0.0)
grape
newrelic_rpm
newrelic_rpm (3.9.4.245)
nokogiri (1.6.6.2)
nokogiri (1.6.6.4)
mini_portile (~> 0.6.0)
nprogress-rails (0.1.6.7)
oauth (0.4.7)
......@@ -440,12 +465,15 @@ GEM
omniauth-github (1.1.2)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1)
omniauth-gitlab (1.0.0)
omniauth-gitlab (1.0.1)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0)
omniauth-google-oauth2 (0.2.6)
omniauth (> 1.0)
omniauth-oauth2 (~> 1.1)
omniauth-google-oauth2 (0.2.10)
addressable (~> 2.3)
jwt (~> 1.0)
multi_json (~> 1.3)
omniauth (>= 1.1.1)
omniauth-oauth2 (~> 1.3.1)
omniauth-kerberos (0.3.0)
omniauth-multipassword
timfel-krb5-auth (~> 0.8)
......@@ -469,18 +497,18 @@ GEM
activesupport
nokogiri (>= 1.4.4)
omniauth (~> 1.0)
opennebula (4.12.1)
opennebula (4.14.2)
json
nokogiri
rbvmomi
org-ruby (0.9.12)
rubypants (~> 0.2)
orm_adapter (0.5.0)
paranoia (2.1.3)
paranoia (2.1.4)
activerecord (~> 4.0)
parser (2.2.2.6)
parser (2.2.3.0)
ast (>= 1.1, < 3.0)
pg (0.18.2)
pg (0.18.4)
poltergeist (1.6.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
......@@ -488,7 +516,7 @@ GEM
websocket-driver (>= 0.2.0)
posix-spawn (0.3.11)
powerpack (0.0.9)
pry (0.10.1)
pry (0.10.3)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
......@@ -497,7 +525,7 @@ GEM
pyu-ruby-sasl (0.0.3.3)
quiet_assets (1.0.3)
railties (>= 3.1, < 5.0)
rack (1.5.5)
rack (1.6.4)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (4.3.0)
......@@ -505,7 +533,7 @@ GEM
rack-cors (0.4.0)
rack-mount (0.8.3)
rack (>= 1.0.0)
rack-oauth2 (1.0.10)
rack-oauth2 (1.2.1)
activesupport (>= 2.3)
attr_required (>= 0.0.5)
httpclient (>= 2.4)
......@@ -515,28 +543,35 @@ GEM
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.1.14)
actionmailer (= 4.1.14)
actionpack (= 4.1.14)
actionview (= 4.1.14)
activemodel (= 4.1.14)
activerecord (= 4.1.14)
activesupport (= 4.1.14)
rails (4.2.4)
actionmailer (= 4.2.4)
actionpack (= 4.2.4)
actionview (= 4.2.4)
activejob (= 4.2.4)
activemodel (= 4.2.4)
activerecord (= 4.2.4)
activesupport (= 4.2.4)
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.14)
sprockets-rails (~> 2.0)
rails-observers (0.1.2)
activemodel (~> 4.0)
railties (4.1.14)
actionpack (= 4.1.14)
activesupport (= 4.1.14)
railties (= 4.2.4)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.7)
activesupport (>= 4.2.0.beta, < 5.0)
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)
thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
raindrops (0.15.0)
rake (10.4.2)
raphael-rails (2.1.2)
rb-fsevent (0.9.5)
rb-fsevent (0.9.6)
rb-inotify (0.9.5)
ffi (>= 0.5.0)
rblineprof (0.3.6)
......@@ -548,13 +583,13 @@ GEM
rdoc (3.12.2)
json (~> 1.4)
redcarpet (3.3.3)
redis (3.2.1)
redis-actionpack (4.0.0)
redis (3.2.2)
redis-actionpack (4.0.1)
actionpack (~> 4)
redis-rack (~> 1.5.0)
redis-store (~> 1.1.0)
redis-activesupport (4.1.1)
activesupport (~> 4)
redis-activesupport (4.1.5)
activesupport (>= 3, < 5)
redis-store (~> 1.1.0)
redis-namespace (1.5.2)
redis (~> 3.0, >= 3.0.4)
......@@ -565,13 +600,13 @@ GEM
redis-actionpack (~> 4)
redis-activesupport (~> 4)
redis-store (~> 1.1.0)
redis-store (1.1.6)
redis-store (1.1.7)
redis (>= 2.2)
request_store (1.2.0)
request_store (1.2.1)
rerun (0.10.0)
listen (~> 2.7, >= 2.7.3)
responders (1.1.2)
railties (>= 3.2, < 4.2)
responders (2.1.0)
railties (>= 4.2.0, < 5)
rest-client (1.8.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0)
......@@ -716,16 +751,16 @@ GEM
term-ansicolor (1.3.2)
tins (~> 1.0)
terminal-table (1.5.2)
test_after_commit (0.2.7)
test_after_commit (0.4.2)
activerecord (>= 3.2)
thin (1.6.3)
thin (1.6.4)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0)
eventmachine (~> 1.0, >= 1.0.4)
rack (~> 1.0)
thor (0.19.1)
thread_safe (0.3.5)
tilt (1.4.1)
timers (4.0.4)
timers (4.1.1)
hitimes
timfel-krb5-auth (0.8.3)
tinder (1.10.1)
......@@ -758,9 +793,9 @@ GEM
kgio (~> 2.6)
rack
raindrops (~> 0.7)
unicorn-worker-killer (0.4.3)
unicorn-worker-killer (0.4.4)
get_process_mem (~> 0)
unicorn (~> 4)
unicorn (>= 4, < 6)
uniform_notifier (1.9.0)
uuid (2.3.8)
macaddr (~> 1.0)
......@@ -772,10 +807,15 @@ GEM
equalizer (~> 0.0, >= 0.0.9)
warden (1.2.3)
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)
addressable (>= 2.3.6)
crack (>= 0.3.2)
websocket-driver (0.6.2)
websocket-driver (0.6.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
wikicloth (0.8.1)
......@@ -797,7 +837,7 @@ DEPENDENCIES
addressable (~> 2.3.8)
after_commit_queue
annotate (~> 2.6.0)
asana (~> 0.0.6)
asana (~> 0.4.0)
asciidoctor (~> 1.5.2)
attr_encrypted (~> 1.3.4)
awesome_print (~> 1.2.0)
......@@ -816,10 +856,9 @@ DEPENDENCIES
carrierwave (~> 0.9.0)
charlock_holmes (~> 0.7.3)
coffee-rails (~> 4.1.0)
colored (~> 1.2)
colorize (~> 0.5.8)
colorize (~> 0.7.0)
coveralls (~> 0.8.2)
creole (~> 0.3.6)
creole (~> 0.5.0)
d3_rails (~> 3.5.5)
database_cleaner (~> 1.4.0)
default_value_for (~> 3.0.0)
......@@ -827,11 +866,10 @@ DEPENDENCIES
devise-async (~> 0.9.0)
devise-two-factor (~> 2.0.0)
diffy (~> 3.0.3)
doorkeeper (~> 2.1.3)
doorkeeper (~> 2.2.0)
dropzonejs-rails (~> 0.7.1)
email_reply_parser (~> 0.5.8)
email_spec (~> 1.6.0)
enumerize (~> 0.7.0)
factory_girl_rails (~> 4.3.0)
ffaker (~> 2.0.0)
flay
......@@ -850,7 +888,7 @@ DEPENDENCIES
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.0.2)
gon (~> 5.0.0)
gon (~> 6.0.1)
grape (~> 0.13.0)
grape-entity (~> 0.4.2)
gssapi
......@@ -861,7 +899,7 @@ DEPENDENCIES
jquery-atwho-rails (~> 1.3.2)
jquery-rails (~> 3.1.3)
jquery-scrollto-rails (~> 1.4.3)
jquery-turbolinks (~> 2.0.1)
jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 4.2.1)
kaminari (~> 0.16.3)
letter_opener (~> 1.1.2)
......@@ -871,6 +909,7 @@ DEPENDENCIES
mysql2 (~> 0.3.16)
nested_form (~> 0.3.2)
net-ldap
net-ssh (~> 3.0.1)
newrelic-grape
newrelic_rpm (~> 3.9.4.245)
nprogress-rails (~> 0.1.6.7)
......@@ -895,8 +934,9 @@ DEPENDENCIES
quiet_assets (~> 1.0.2)
rack-attack (~> 4.3.0)
rack-cors (~> 0.4.0)
rack-oauth2 (~> 1.0.5)
rails (= 4.1.14)
rack-oauth2 (~> 1.2.1)
rails (= 4.2.4)
rails-deprecated_sanitizer (~> 1.0.3)
raphael-rails (~> 2.1.2)
rblineprof
rdoc (~> 3.6)
......@@ -904,6 +944,7 @@ DEPENDENCIES
redis-rails (~> 4.0.0)
request_store (~> 1.2.0)
rerun (~> 0.10.0)
responders (~> 2.0)
rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.3.0)
rubocop (~> 0.28.0)
......@@ -933,7 +974,7 @@ DEPENDENCIES
task_list (~> 1.0.2)
teaspoon (~> 1.0.0)
teaspoon-jasmine (~> 2.2.0)
test_after_commit (~> 0.2.2)
test_after_commit (~> 0.4.2)
thin (~> 1.6.1)
tinder (~> 1.10.0)
turbolinks (~> 2.5.0)
......@@ -944,6 +985,7 @@ DEPENDENCIES
unicorn-worker-killer (~> 0.4.2)
version_sorter (~> 2.0.0)
virtus (~> 1.0.1)
web-console (~> 2.0)
webmock (~> 1.21.0)
wikicloth (= 0.8.1)
......
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
#= require clipboard
$ ->
clipboard = new Clipboard '.js-clipboard-trigger',
text: (trigger) ->
$target = $(trigger.nextElementSibling || trigger.previousElementSibling)
$target.data('clipboard-text') || $target.text().trim()
genericSuccess = (e) ->
showTooltip(e.trigger, 'Copied!')
# Clear the selection and blur the trigger so it loses its border
e.clearSelection()
$(e.trigger).blur()
clipboard.on 'success', (e) ->
$(e.trigger).
tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!').
tooltip('show').
one('mouseleave', -> $(this).tooltip('hide'))
# Safari doesn't support `execCommand`, so instead we inform the user to
# copy manually.
#
# See http://clipboardjs.com/#browser-support
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
e.clearSelection()
$(e.trigger).blur()
showTooltip(e.trigger, "Press #{key}-C to copy")
# Safari doesn't support `execCommand`, so instead we inform the user to
# copy manually.
#
# See http://clipboardjs.com/#browser-support
clipboard.on 'error', (e) ->
if /Mac/i.test(navigator.userAgent)
title = "Press &#8984;-C to copy"
else
title = "Press Ctrl-C to copy"
showTooltip = (target, title) ->
$(target).
tooltip(
container: 'body'
html: 'true'
placement: 'auto bottom'
title: title
trigger: 'manual'
).
tooltip('show').
one('mouseleave', -> $(this).tooltip('hide'))
$(e.trigger).
tooltip(trigger: 'manual', placement: 'auto bottom', html: true, title: title).
tooltip('show').
one('mouseleave', -> $(this).tooltip('hide'))
$ ->
clipboard = new Clipboard '[data-clipboard-target], [data-clipboard-text]'
clipboard.on 'success', genericSuccess
clipboard.on 'error', genericError
#= require markdown_preview
class @DropzoneInput
constructor: (form) ->
Dropzone.autoDiscover = false
......@@ -11,17 +13,14 @@ class @DropzoneInput
uploadProgress = $("<div class=\"div-dropzone-progress\"></div>")
btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
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
form_textarea = $(form).find("textarea.markdown-area")
form_textarea.wrap "<div class=\"div-dropzone\"></div>"
form_textarea.on 'paste', (event) =>
handlePaste(event)
form_textarea.on "input", ->
hideReferencedUsers()
form_textarea.on "blur", ->
renderMarkdown()
$(form).setupMarkdownPreview()
form_dropzone = $(form).find('.div-dropzone')
form_dropzone.parent().addClass "div-dropzone-wrapper"
......@@ -34,42 +33,6 @@ class @DropzoneInput
"opacity": 0
"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(
url: project_uploads_path
dictDefaultMessage: ""
......@@ -136,41 +99,6 @@ class @DropzoneInput
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) ->
text = "[#{link.alt}](#{link.url})"
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
constructor: ->
# Git clone panel switcher
cloneHolder = $('.git-clone-holder')
if cloneHolder.length
$('a, button', cloneHolder).click ->
$('a, button', cloneHolder).removeClass 'active'
$(@).addClass 'active'
$('#project_clone', cloneHolder).val $(@).data 'clone'
$(".clone").text("").append $(@).data 'clone'
# Git protocol switcher
$('.js-protocol-switch').click ->
return if $(@).hasClass('active')
# Toggle 'active' for both buttons
$('.js-protocol-switch').toggleClass('active')
url = $(@).data('clone')
# Update the input field
$('#project_clone').val(url)
# Update the command line instructions
$('.clone').text(url)
# Ref switcher
$('.project-refs-select').on 'change', ->
......@@ -39,4 +45,4 @@ class @Project
when 4 then label = ' On Mention '
$('#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'
$(@).parent().addClass 'active'
\ No newline at end of file
$(@).parent().addClass 'active'
......@@ -127,3 +127,8 @@ ul.content-list {
}
}
.panel > .content-list {
li {
margin: 0;
}
}
......@@ -32,3 +32,7 @@
}
}
}
.panel > .gl-pagination {
margin: 0;
}
......@@ -256,3 +256,9 @@ textarea.js-gfm-input {
.strikethrough {
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 {
float: left;
}
......@@ -15,4 +10,4 @@
.form-control {
height: 42px;
}
}
\ No newline at end of file
}
......@@ -90,7 +90,12 @@
}
.visibility-level-label {
@extend .btn;
@extend .btn-gray;
color: $gray;
cursor: auto;
i {
color: inherit;
}
......@@ -178,6 +183,11 @@
&:active {
outline: none;
}
&.btn-clipboard {
padding-left: 15px;
padding-right: 15px;
}
}
.active {
......@@ -556,4 +566,4 @@ pre.light-well {
z-index: 100;
position: relative;
}
}
\ No newline at end of file
}
......@@ -10,7 +10,7 @@ class AbuseReportsController < ApplicationController
if @abuse_report.save
if current_application_settings.admin_notification_email.present?
AbuseReportMailer.delay.notify(@abuse_report.id)
AbuseReportMailer.notify(@abuse_report.id).deliver_later
end
message = "Thank you for your report. A GitLab administrator will look into it shortly."
......
......@@ -67,7 +67,12 @@ class Projects::CommitController < Projects::ApplicationController
end
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
@builds = ci_commit.builds if ci_commit
......
......@@ -164,12 +164,10 @@ class Projects::IssuesController < Projects::ApplicationController
end
def issue_params
permitted = params.require(:issue).permit(
params.require(:issue).permit(
:title, :assignee_id, :position, :description,
:milestone_id, :state_event, :task_num, label_ids: []
)
params[:issue][:title].strip! if params[:issue][:title]
permitted
end
def bulk_update_params
......
......@@ -325,13 +325,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def merge_request_params
permitted = params.require(:merge_request).permit(
params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id, :approver_ids,
:state_event, :description, :task_num, label_ids: []
)
params[:merge_request][:title].strip! if params[:merge_request][:title]
permitted
end
# Make sure merge requests created before 8.0
......
......@@ -124,7 +124,7 @@ class ProjectsController < ApplicationController
::Projects::DestroyService.new(@project, current_user, {}).execute
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
redirect_to edit_project_path(@project), alert: ex.message
end
......
......@@ -2,7 +2,7 @@ class SnippetsController < ApplicationController
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw]
# Allow read snippet
before_action :authorize_read_snippet!, only: [:show]
before_action :authorize_read_snippet!, only: [:show, :raw]
# Allow modify snippet
before_action :authorize_update_snippet!, only: [:edit, :update]
......
......@@ -68,7 +68,7 @@ module ApplicationHelper
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)
user = user_or_email
else
......@@ -78,12 +78,12 @@ module ApplicationHelper
if user
user.avatar_url(size) || default_avatar
else
gravatar_icon(user_or_email, size)
gravatar_icon(user_or_email, size, scale)
end
end
def gravatar_icon(user_email = '', size = nil)
GravatarService.new.execute(user_email, size) ||
def gravatar_icon(user_email = '', size = nil, scale = 2)
GravatarService.new.execute(user_email, size, scale) ||
default_avatar
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
return "View #{action.humanize.singularize}"
end
end
nil
end
def color_email_diff(diffcontent)
......
......@@ -173,8 +173,7 @@ module ProjectsHelper
'unknown'
end
def default_url_to_repo(project = nil)
project = project || @project
def default_url_to_repo(project = @project)
current_user ? project.url_to_repo : project.http_url_to_repo
end
......
......@@ -8,10 +8,6 @@ class BaseMailer < ActionMailer::Base
default from: Proc.new { default_sender_address.format }
default reply_to: Proc.new { default_reply_to_address.format }
def self.delay
delay_for(2.seconds)
end
def can?
Ability.abilities.allowed?(current_user, action, subject)
end
......
......@@ -74,15 +74,23 @@ class ApplicationSetting < ActiveRecord::Base
end
after_commit do
Rails.cache.write('application_setting.last', self)
Rails.cache.write(cache_key, self)
end
def self.current
Rails.cache.fetch('application_setting.last') do
Rails.cache.fetch(cache_key) do
ApplicationSetting.last
end
end
def self.expire
Rails.cache.delete(cache_key)
end
def self.cache_key
'application_setting.last'
end
def self.create_from_defaults
create(
default_projects_limit: Settings.gitlab['default_projects_limit'],
......
......@@ -14,11 +14,15 @@ module Ci
extend Ci::Model
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
def self.current
Rails.cache.fetch('ci_application_setting.last') do
Rails.cache.fetch(cache_key) do
Ci::ApplicationSetting.last
end
end
......@@ -29,5 +33,9 @@ module Ci
add_pusher: Settings.gitlab_ci['add_pusher'],
)
end
def self.cache_key
'ci_application_setting.last'
end
end
end
......@@ -8,6 +8,7 @@ module Issuable
extend ActiveSupport::Concern
include Participable
include Mentionable
include StripAttribute
included do
belongs_to :author, class_name: "User"
......@@ -51,6 +52,7 @@ module Issuable
attr_mentionable :title, :description
participant :author, :assignee, :notes_with_associations
strip_attributes :title
end
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
include InternalId
include Sortable
include StripAttribute
belongs_to :project
has_many :issues
......@@ -35,6 +36,8 @@ class Milestone < ActiveRecord::Base
validates :title, presence: true
validates :project, presence: true
strip_attributes :title
state_machine :state, initial: :active do
event :close do
transition active: :closed
......
......@@ -44,7 +44,6 @@ class Project < ActiveRecord::Base
include CaseSensitivity
extend Gitlab::ConfigHelper
extend Enumerize
UNKNOWN_IMPORT_URL = 'http://unknown.git'
......
......@@ -64,9 +64,9 @@ module Ci
build.project_recipients.each do |recipient|
case build.status.to_sym
when :success
mailer.build_success_email(build.id, recipient)
mailer.build_success_email(build.id, recipient).deliver_later
when :failed
mailer.build_fail_email(build.id, recipient)
mailer.build_fail_email(build.id, recipient).deliver_later
end
end
end
......@@ -78,7 +78,7 @@ module Ci
end
def mailer
Ci::Notify.delay
Ci::Notify
end
end
end
......@@ -55,7 +55,7 @@ class GitlabCiService < CiService
end
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
def commit_status(sha, ref)
......
......@@ -627,9 +627,13 @@ class Repository
# Run GitLab pre-receive hook
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
# Create branch
rugged.references.create(ref, newrev)
......@@ -652,7 +656,7 @@ class Repository
# Remove tmp ref and return error to user
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
......
......@@ -17,9 +17,8 @@ class SentNotification < ActiveRecord::Base
belongs_to :noteable, polymorphic: true
belongs_to :recipient, class_name: "User"
validate :project, :recipient, :reply_key, presence: true
validate :reply_key, uniqueness: true
validates :project, :recipient, :reply_key, presence: true
validates :reply_key, uniqueness: true
validates :noteable_id, presence: true, unless: :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
......
......@@ -665,11 +665,11 @@ class User < ActiveRecord::Base
email.start_with?('temp-email-for-oauth')
end
def avatar_url(size = nil)
def avatar_url(size = nil, scale = 2)
if avatar.present?
[gitlab_config.url, avatar.url].join
else
GravatarService.new.execute(email, size)
GravatarService.new.execute(email, size, scale)
end
end
......
class GravatarService
include Gitlab::CurrentSettings
def execute(email, size = nil)
def execute(email, size = nil, scale = 2)
if current_application_settings.gravatar_enabled? && email.present?
size = 40 if size.nil? || size <= 0
sprintf gravatar_url,
hash: Digest::MD5.hexdigest(email.strip.downcase),
size: size,
size: size * scale,
email: email.strip
end
end
......
......@@ -38,7 +38,7 @@ module MergeRequests
}
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")
Rails.logger.error(e.message)
return false
......
......@@ -13,14 +13,14 @@ class NotificationService
# even if user disabled notifications
def new_key(key)
if key.user
mailer.new_ssh_key_email(key.id)
mailer.new_ssh_key_email(key.id).deliver_later
end
end
# Always notify user about email added to profile
def new_email(email)
if email.user
mailer.new_email_email(email.id)
mailer.new_email_email(email.id).deliver_later
end
end
......@@ -79,17 +79,27 @@ class NotificationService
end
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
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
# Notify new user with email after creation
def new_user(user, token = nil)
# 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
# Notify users on new note in system
......@@ -138,50 +148,59 @@ class NotificationService
# build notify method like 'note_commit_email'
notify_method = "note_#{note.noteable_type.underscore}_email".to_sym
recipients.each do |recipient|
mailer.send(notify_method, recipient.id, note.id)
mailer.send(notify_method, recipient.id, note.id).deliver_later
end
end
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
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
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
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
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
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
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
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
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
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
def project_was_moved(project, old_path_with_namespace)
......@@ -189,7 +208,11 @@ class NotificationService
recipients = reject_muted_users(recipients, project)
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
......@@ -339,7 +362,7 @@ class NotificationService
recipients = build_recipients(target, project, target.author)
recipients.each do |recipient|
mailer.send(method, recipient.id, target.id)
mailer.send(method, recipient.id, target.id).deliver_later
end
end
......@@ -347,7 +370,7 @@ class NotificationService
recipients = build_recipients(target, project, current_user)
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
......@@ -358,7 +381,13 @@ class NotificationService
recipients = build_recipients(target, project, current_user, [previous_assignee])
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
......@@ -366,7 +395,7 @@ class NotificationService
recipients = build_recipients(target, project, current_user)
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
......@@ -388,7 +417,7 @@ class NotificationService
end
def mailer
Notify.delay
Notify
end
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 @@
.row
.col-md-6
- if @personal_projects.present?
= render 'users/projects', projects: @personal_projects
= render 'admin/users/projects', projects: @personal_projects
- else
.nothing-here-block This user has no personal projects.
......
......@@ -37,7 +37,7 @@
= label_tag :tag_list, class: 'control-label' do
Tags
.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
.form-actions
= f.submit 'Save', class: 'btn btn-save'
......
......@@ -8,7 +8,7 @@
= @project.name
%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
Author: #{@build.commit.git_author_name}
%p
......
......@@ -4,7 +4,7 @@
%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
%span{class: ("list-item-name" if show_controls)}
- if member.user
= image_tag avatar_icon(user, 16), class: "avatar s16", alt: ''
= image_tag avatar_icon(user, 24), class: "avatar s24", alt: ''
%strong
= link_to user.name, user_path(user)
%span.cgray= user.username
......@@ -14,7 +14,7 @@
%label.label.label-danger
%strong Blocked
- 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
= member.invite_email
%span.cgray
......@@ -30,7 +30,7 @@
- if should_user_see_group_roles?(current_user, @group)
%span.pull-right
%strong= member.human_access
%strong.member-access-level= member.human_access
- if show_controls
- if can?(current_user, :update_group_member, member)
= button_tag class: "btn-xs btn js-toggle-button",
......
- page_title "Members"
- header_title group_title(@group, "Members", group_group_members_path(@group))
- if should_user_see_group_roles?(current_user, @group)
%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'
- @blank_container = true
.group-members-page
- if current_user && current_user.can?(:admin_group_member, @group)
<<<<<<< HEAD
.pull-right
- if @group.ldap_synced?
= form_tag(reset_access_group_ldap_path(@group), method: :put, class: 'inline') do
......@@ -53,6 +44,34 @@
= paginate @members, theme: 'gitlab'
= 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
$('form.member-search-form').on('submit', function(event) {
......
- 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_icon(@project, alt: '', class: 'project-avatar avatar s90')
.project-home-desc
......@@ -12,6 +12,10 @@
Forked from
= link_to project_path(forked_from_project) do
= 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?
- import_url = @project.safe_import_url
......@@ -27,7 +31,7 @@
= render 'projects/buttons/fork'
= render "shared/clone_panel"
.split-repo-buttons
= render "projects/buttons/update_mirror"
= render "projects/buttons/download"
......
......@@ -5,7 +5,7 @@
%a.js-md-write-button(href="#md-write-holder" tabindex="-1")
Write
%li
%a.js-md-preview-button(href="md-preview-holder" tabindex="-1")
%a.js-md-preview-button(href="#md-preview-holder" tabindex="-1")
Preview
- if defined?(referenced_users) && referenced_users
......
......@@ -20,8 +20,8 @@
- if ci_commit
= render_ci_status(ci_commit)
&nbsp;
= clipboard_button
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id", data: {clipboard_text: commit.id}
= clipboard_button(clipboard_text: commit.id)
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
.notes_count
- if note_count > 0
......
......@@ -35,7 +35,7 @@
.form-group
= f.label :tag_list, "Tags", class: 'control-label'
.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.
%fieldset.features
......
......@@ -18,9 +18,9 @@
= link_to_member(@project, participant, name: false, size: 24)
.col-md-3
.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)
= clipboard_button
= clipboard_button(clipboard_target: '#cross-project-reference')
.row
%section.col-md-9
......
......@@ -15,9 +15,9 @@
= render "projects/merge_requests/show/participants"
.col-md-3
.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)
= clipboard_button
= clipboard_button(clipboard_target: '#cross-project-reference')
.row
%section.col-md-9
......
......@@ -4,11 +4,11 @@
group members
%small
(#{members.count})
.panel-head-actions
= link_to group_group_members_path(@group), class: 'btn btn-sm' do
%i.fa.fa-pencil-square-o
.pull-right
= link_to group_group_members_path(@group), class: 'btn' do
= icon('pencil-square-o')
Edit group members
%ul.well-list
%ul.content-list
- members.each do |member|
= render 'groups/group_members/group_member', member: member, show_controls: false
- if members.count > 20
......
......@@ -4,7 +4,7 @@
%li{class: "#{dom_class(member)} js-toggle-container project_member_row access-#{member.human_access.downcase}", id: dom_id(member)}
%span.list-item-name
- if member.user
= image_tag avatar_icon(user, 16), class: "avatar s16", alt: ''
= image_tag avatar_icon(user, 24), class: "avatar s24", alt: ''
%strong
= link_to user.name, user_path(user)
%span.cgray= user.username
......@@ -14,7 +14,7 @@
%label.label.label-danger
%strong Blocked
- 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
= member.invite_email
%span.cgray
......
.panel.panel-default.prepend-top-20
.panel.panel-default
.panel-heading
%strong #{@project.name}
project members
%small
(#{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|
= 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"
= render "header_title"
- @blank_container = true
<<<<<<< HEAD
.gray-content-block.top-block
.clearfix.js-toggle-container
= form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do
......@@ -34,9 +36,22 @@
= render "group_members", members: @group_members
- if @project_group_links.any? && @project.allowed_to_share_with_group?
= 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
$('form.member-search-form').on('submit', function (event) {
event.preventDefault();
Turbolinks.visit(this.action + '?' + $(this).serialize());
});
- if @group
= render "group_members", members: @group_members
......@@ -23,7 +23,7 @@
= label_tag :tag_list, class: 'control-label' do
Tags
.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
.form-actions
= f.submit 'Save', class: 'btn btn-save'
......@@ -2,25 +2,9 @@
.git-clone-holder.input-group
.input-group-addon.git-protocols
.input-group-btn
%button{ |
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
= ssh_clone_button(project)
.input-group-btn
%button{ |
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
= http_clone_button(project)
= 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-addon.has_tooltip{title: "#{visibility_level_label(project.visibility_level)} project", data: { container: "body" } }
.visibility-level-label
= visibility_level_icon(project.visibility_level)
.input-group-btn
= clipboard_button(clipboard_target: '#project_clone')
......@@ -25,6 +25,12 @@
%strong
= @transaction.duration.round(2)
= t('sherlock.seconds')
%li
%span.light
#{t('sherlock.query_time')}
%strong
= @transaction.query_duration.round(2)
= t('sherlock.seconds')
%li
%span.light
#{t('sherlock.finished_at')}:
......
......@@ -46,6 +46,6 @@ class EmailReceiverWorker
return
end
EmailRejectionMailer.delay.rejection(reason, raw, can_retry)
EmailRejectionMailer.rejection(reason, raw, can_retry).deliver_later
end
end
......@@ -53,7 +53,7 @@ class EmailsOnPushWorker
reverse_compare: reverse_compare,
send_from_committer_email: send_from_committer_email,
disable_diffs: disable_diffs
).deliver
).deliver_now
# These are input errors and won't be corrected even if Sidekiq retries
rescue Net::SMTPFatalError, Net::SMTPSyntaxError => 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
begin
load File.expand_path("../spring", __FILE__)
rescue LoadError
end
APP_PATH = File.expand_path('../../config/application', __FILE__)
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
#!/usr/bin/env ruby
begin
load File.expand_path("../spring", __FILE__)
rescue LoadError
end
require 'bundler/setup'
load Gem.bin_path('rake', 'rake')
require_relative '../config/boot'
require 'rake'
Rake.application.run
#!/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
redis_config_hash[:expires_in] = 2.weeks # Cache should not grow forever
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
ENV['GITLAB_PATH_OUTSIDE_HOOK'] = ENV['PATH']
end
......
......@@ -2,4 +2,4 @@
require File.expand_path('../application', __FILE__)
# 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
# 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
# Code is not reloaded between requests
......@@ -9,7 +9,7 @@ Gitlab::Application.configure do
config.action_controller.perform_caching = true
# 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.
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
# The test environment is used exclusively to run your application's
......@@ -8,7 +8,7 @@ Gitlab::Application.configure do
config.cache_classes = false
# 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"
# Show full error reports and disable caching
......@@ -32,4 +32,6 @@ Gitlab::Application.configure do
config.eager_load = false
config.cache_store = :null_store
config.active_job.queue_adapter = :test
end
......@@ -33,13 +33,15 @@ class Settings < Settingslogic
end
def build_gitlab_shell_ssh_path_prefix
user_host = "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}"
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
if gitlab_shell.ssh_host.include? ':'
"[#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}]:"
"[#{user_host}]:"
else
"#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:"
"#{user_host}:"
end
end
end
......@@ -332,3 +334,12 @@ if Rails.env.test?
Settings.gitlab['default_can_create_group'] = true
Settings.gitlab['default_can_create_team'] = false
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.
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?
default_url_options[:port] = Gitlab.config.gitlab.port
end
Gitlab::Application.routes.default_url_options = default_url_options
Rails.application.routes.default_url_options = default_url_options
......@@ -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
paths_to_be_protected = [
"#{Gitlab::Application.config.relative_url_root}/users/password",
"#{Gitlab::Application.config.relative_url_root}/users/sign_in",
"#{Gitlab::Application.config.relative_url_root}/api/#{API::API.version}/session.json",
"#{Gitlab::Application.config.relative_url_root}/api/#{API::API.version}/session",
"#{Gitlab::Application.config.relative_url_root}/users",
"#{Gitlab::Application.config.relative_url_root}/users/confirmation",
"#{Gitlab::Application.config.relative_url_root}/unsubscribes/"
"#{Rails.application.config.relative_url_root}/users/password",
"#{Rails.application.config.relative_url_root}/users/sign_in",
"#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session.json",
"#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session",
"#{Rails.application.config.relative_url_root}/users",
"#{Rails.application.config.relative_url_root}/users/confirmation",
"#{Rails.application.config.relative_url_root}/unsubscribes/"
]
......
......@@ -2,7 +2,7 @@
# with darker backgrounds. This patch tweaks the colors a bit so the output is
# actually readable.
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
class Lineprof
......
......@@ -22,15 +22,15 @@ def find_secure_token
end
end
Gitlab::Application.config.secret_token = find_secure_token
Gitlab::Application.config.secret_key_base = find_secure_token
Rails.application.config.secret_token = find_secure_token
Rails.application.config.secret_key_base = find_secure_token
# CI
def generate_new_secure_token
SecureRandom.hex(64)
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`"
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?
file.write(YAML.dump(all_secrets))
end
Gitlab::Application.secrets.db_key_base = env_secrets['db_key_base']
Rails.application.secrets.db_key_base = env_secrets['db_key_base']
end
......@@ -3,20 +3,21 @@
require 'gitlab/current_settings'
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
Settings.gitlab['session_expire_delay'] = current_application_settings.session_expire_delay
Settings.gitlab['session_expire_delay'] = current_application_settings.session_expire_delay || 10080
rescue
Settings.gitlab['session_expire_delay'] ||= 10080
end
unless Rails.env.test?
Gitlab::Application.config.session_store(
: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',
secure: Gitlab.config.gitlab.https,
httponly: true,
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
if Gitlab::Sherlock.enabled?
Gitlab::Application.configure do |config|
Rails.application.configure do |config|
config.middleware.use(Gitlab::Sherlock::Middleware)
end
end
......@@ -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 Rails.env.production?
Gitlab::Application.config.action_mailer.delivery_method = :smtp
Rails.application.config.action_mailer.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
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
# by checking if they exist in the `/public` directory.
# We're replacing it with our `Gitlab::Middleware::Static` that does the same,
......
......@@ -35,3 +35,4 @@ en:
events: Events
percent: '%'
count: Count
query_time: Query Time
require 'sidekiq/web'
require 'api/api'
Gitlab::Application.routes.draw do
Rails.application.routes.draw do
if Gitlab::Sherlock.enabled?
namespace :sherlock do
resources :transactions, only: [:index, :show] do
......
......@@ -16,7 +16,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
# These are extensions that must be enabled in order to support this database
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 "user_id"
t.text "message"
......@@ -24,17 +24,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.datetime "updated_at"
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|
t.integer "default_projects_limit"
t.boolean "signup_enabled"
......@@ -63,24 +52,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.integer "max_artifacts_size", default: 100, null: false
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|
t.integer "author_id", null: false
t.string "type", null: false
......@@ -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", ["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.datetime "starts_at"
t.datetime "ends_at"
......@@ -106,14 +77,14 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.string "font"
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 "add_pusher"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "ci_builds", force: true do |t|
create_table "ci_builds", force: :cascade do |t|
t.integer "project_id"
t.string "status"
t.datetime "finished_at"
......@@ -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", ["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.string "ref"
t.string "sha"
......@@ -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", ["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 "user_id"
t.integer "is_admin"
......@@ -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", ["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.text "commands"
t.boolean "active", default: true, null: false
......@@ -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", ["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.integer "timeout", default: 3600, null: false
t.datetime "created_at"
......@@ -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", ["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 "project_id", null: false
t.datetime "created_at"
......@@ -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", ["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.datetime "created_at"
t.datetime "updated_at"
......@@ -255,7 +226,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.string "architecture"
end
create_table "ci_services", force: true do |t|
create_table "ci_services", force: :cascade do |t|
t.string "type"
t.string "title"
t.integer "project_id", null: false
......@@ -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
create_table "ci_sessions", force: true do |t|
create_table "ci_sessions", force: :cascade do |t|
t.string "session_id", null: false
t.text "data"
t.datetime "created_at"
......@@ -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", ["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 "taggable_id"
t.string "taggable_type"
......@@ -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", ["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.integer "taggings_count", default: 0
end
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.text "variables"
t.datetime "created_at"
......@@ -305,7 +276,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
t.integer "commit_id"
end
create_table "ci_triggers", force: true do |t|
create_table "ci_triggers", force: :cascade do |t|
t.string "token"
t.integer "project_id", null: false
t.datetime "deleted_at"
......@@ -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
create_table "ci_variables", force: true do |t|
create_table "ci_variables", force: :cascade do |t|
t.integer "project_id", null: false
t.string "key"
t.text "value"
......@@ -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
create_table "ci_web_hooks", force: true do |t|
create_table "ci_web_hooks", force: :cascade do |t|
t.string "url", null: false
t.integer "project_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
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 "project_id", null: false
t.datetime "created_at"
......@@ -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
create_table "emails", force: true do |t|
create_table "emails", force: :cascade do |t|
t.integer "user_id", null: false
t.string "email", null: false
t.datetime "created_at"
......@@ -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", ["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.integer "target_id"
t.string "title"
......@@ -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_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_from_project_id", null: false
t.datetime "created_at"
......@@ -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
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|
t.string "extern_uid"
t.string "provider"
......@@ -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", ["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.integer "assignee_id"
t.integer "author_id"
......@@ -439,7 +388,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "issues", ["state"], name: "index_issues_on_state", 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.datetime "created_at"
t.datetime "updated_at"
......@@ -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", ["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 "target_id"
t.string "target_type"
......@@ -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", ["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 "color"
t.integer "project_id"
......@@ -475,15 +424,6 @@ ActiveRecord::Schema.define(version: 20151118162244) do
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|
t.string "oid", null: false
t.integer "size", null: false
......@@ -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
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 "project_id", null: false
t.datetime "created_at"
......@@ -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
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|
t.integer "access_level", null: false
t.integer "source_id", null: false
......@@ -531,7 +465,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "members", ["type"], name: "index_members_on_type", 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.text "st_commits"
t.text "st_diffs"
......@@ -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
create_table "merge_requests", force: true do |t|
create_table "merge_requests", force: :cascade do |t|
t.string "target_branch", null: false
t.string "source_branch", null: false
t.integer "source_project_id", null: false
......@@ -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", ["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.integer "project_id", null: false
t.text "description"
......@@ -591,8 +525,8 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree
create_table "namespaces", force: true do |t|
t.string "name", null: false
t.string "path", null: false
t.string "name", null: false
t.string "path", null: false
t.integer "owner_id"
t.datetime "created_at"
t.datetime "updated_at"
......@@ -611,7 +545,7 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "namespaces", ["public"], name: "index_namespaces_on_public", using: :btree
add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree
create_table "notes", force: true do |t|
create_table "notes", force: :cascade do |t|
t.text "note"
t.string "noteable_type"
t.integer "author_id"
......@@ -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", ["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 "application_id", null: false
t.string "token", null: false
......@@ -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
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 "application_id"
t.string "token", null: false
......@@ -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", ["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 "uid", null: false
t.string "secret", null: false
......@@ -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", ["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|
t.integer "project_id"
t.text "data"
end
create_table "projects", force: true do |t|
create_table "projects", force: :cascade do |t|
t.string "name"
t.string "path"
t.text "description"
......@@ -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", ["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.string "name", null: false
t.datetime "created_at"
......@@ -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
create_table "releases", force: true do |t|
create_table "releases", force: :cascade do |t|
t.string "tag"
t.text "description"
t.integer "project_id"
......@@ -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"], 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 "noteable_id"
t.string "noteable_type"
......@@ -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
create_table "services", force: true do |t|
create_table "services", force: :cascade do |t|
t.string "type"
t.string "title"
t.integer "project_id"
......@@ -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", ["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.text "content"
t.integer "author_id", null: false
......@@ -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", ["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 "subscribable_id"
t.string "subscribable_type"
......@@ -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
create_table "taggings", force: true do |t|
create_table "taggings", force: :cascade do |t|
t.integer "tag_id"
t.integer "taggable_id"
t.string "taggable_type"
......@@ -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", ["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.integer "taggings_count", default: 0
end
......@@ -848,8 +774,8 @@ ActiveRecord::Schema.define(version: 20151118162244) do
add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
......@@ -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", ["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 "user_id", null: false
t.datetime "created_at"
......@@ -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"], 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.integer "project_id"
t.datetime "created_at"
......
# 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.
Push your application to that repository.
From there on, on every push to your git repository the build will be
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.
Point your browser to the URL you have set GitLab or use [gitlab.com/ci](https://gitlab.com/ci/).
## Creating a `.gitlab-ci.yml` file
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**.
This will create project in CI and authorize GitLab CI to fetch sources from GitLab.
The `.gitlab-ci.yml` file is where you configure what CI does with your project.
It lives in the root of your repository.
> GitLab CI creates unique token that is used to configure GitLab CI service in GitLab.
> This token allows to access GitLab's repository and configures GitLab to trigger GitLab CI webhook on **Push events** and **Tag push events**.
> You can see that token by going to Project's Settings > Services > GitLab CI.
> You will see there token, the same token is assigned in GitLab CI settings of project.
On any push to your repository, GitLab will look for the `.gitlab-ci.yml`
file and start builds on _Runners_ according to the contents of the file,
for that commit.
## 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.
GitLab CI uses [YAML](https://en.wikipedia.org/wiki/YAML) file to store build configuration.
You need to create `.gitlab-ci.yml` in root directory of your repository:
**Note:** `.gitlab-ci.yml` is a [YAML](https://en.wikipedia.org/wiki/YAML) file
so you have to pay extra attention to the identation. Always use spaces, not
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
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:
script:
......@@ -49,71 +67,131 @@ rubocop:
- bundle exec rubocop
```
This is the simplest possible build configuration that will work for most Ruby applications:
1. Define two jobs `rspec` and `rubocop` with two different commands to be executed.
1. Before every job execute commands defined by `before_script`.
This is the simplest possible build configuration that will work for most Ruby
applications:
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 jobs are defined as top-level elements with name and always have to contain the `script`.
Jobs are used to create builds, which are then picked by [runners](../runners/README.md) and executed within environment of the runner.
What is important that each job is run independently from each other.
The `.gitlab-ci.yml` file defines sets of jobs with constraints of how and when
they should be run. The jobs are defined as top-level elements with a name (in
our case `rspec` and `rubocop`) and always have to contain the `script` keyword.
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
git add .gitlab-ci.yml
git commit
git commit -m "Add .gitlab-ci.yml"
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.
A runner is a machine (can be virtual, bare-metal or VPS) that picks up builds through the coordinator API of GitLab CI.
These are special virtual machines that run on GitLab's infrastructure and can
build any project.
A runner can be specific to a certain project or serve any project in GitLab CI.
A runner that serves all projects is called a shared runner.
More information about different runner types can be found in [Configuring runner](../runners/README.md).
To enable **Shared Runners** you have to go to your project's
**Settings > Runners** and click **Enable shared runners**.
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.
1. Specify following URL during runner setup: https://gitlab.com/ci/
1. Use the following registration token during setup: TOKEN
## Seeing the status of your build
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.
These are special virtual machines that are run on GitLab's infrastructure that can build any project.
To enable **Shared runners** you have to go to **Runners** and click **Enable shared runners** for this project.
By clicking on a Build ID, you will be able to see the log of that build.
This is important to diagnose why a build failed or acted differently than
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.
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.
Visit our various languages examples at <https://gitlab.com/groups/gitlab-examples>.
GitLab CI also offers **the Lint** tool to verify validity of your `.gitlab-ci.yml` which can be useful to troubleshoot potential problems.
The Lint is available from project's settings or by adding `/lint` to GitLab CI url.
[runner-install]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/tree/master#installation
[blog-ci]: https://about.gitlab.com/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/
# 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.
## Public projects
## Visibility of projects
### Public projects
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.
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. Click on the "Edit" tab
1. Change "Visibility Level"
1. Go to your project's **Settings**
1. Change "Visibility Level" to either Public, Internal or Private
## 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.
- You are logged out, and the target user is authorized to (is Guest, Reporter, etc.) at least one public project.
## Visibility of groups
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
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
# Start GitLab
sudo gitlab-ctl start
# Create satellites
sudo gitlab-rake gitlab:satellites:create
# Check GitLab
sudo gitlab-rake gitlab:check SANITIZE=true
```
......
......@@ -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.
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
When I press create mileston button
Then milestone in each project should be created
# Group projects in settings
Scenario: I should see all projects in the project list in settings
Given Group "Owned" has archived project
......
......@@ -13,14 +13,12 @@ Feature: Project Team Management
@javascript
Scenario: Add user to project
Given I click link "Add members"
And I select "Mike" as "Reporter"
When I select "Mike" as "Reporter"
Then I should see "Mike" in team list as "Reporter"
@javascript
Scenario: Invite user to project
Given I click link "Add members"
And I select "sjobs@apple.com" as "Reporter"
When I select "sjobs@apple.com" as "Reporter"
Then I should see "sjobs@apple.com" in team list as invited "Reporter"
@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
end
step 'Group "Owned" has a public project "Public-project"' do
group = Group.find_by(name: "Owned")
group = owned_group
@project = create :empty_project, :public,
group: group,
......@@ -91,7 +91,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
end
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
end
end
......@@ -214,12 +214,12 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
step 'I change group "Owned" avatar' do
attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif'))
click_button "Save group"
Group.find_by(name: "Owned").reload
owned_group.reload
end
step 'I should see new group "Owned" avatar' do
expect(Group.find_by(name: "Owned").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).to be_instance_of AvatarUploader
expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/banana_sample.gif"
end
step 'I should see the "Remove avatar" button' do
......@@ -229,16 +229,16 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
step 'I have group "Owned" avatar' do
attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif'))
click_button "Save group"
Group.find_by(name: "Owned").reload
owned_group.reload
end
step 'I remove group "Owned" avatar' do
click_link "Remove avatar"
Group.find_by(name: "Owned").reload
owned_group.reload
end
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
step 'I should not see the "Remove avatar" button' do
......@@ -337,14 +337,36 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
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)
project.send(key).where(assignee_id: current_user.id)
end
def project
Group.find_by(name: "Owned").projects.first
owned_group.projects.first
end
def group_milestone
......@@ -412,26 +434,4 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
author: current_user,
milestone: milestone2_project3
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
......@@ -15,10 +15,6 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps
expect(page).to have_content(user.username)
end
step 'I click link "Add members"' do
find(:css, 'button.btn-new').click
end
step 'I select "Mike" as "Reporter"' do
user = User.find_by(name: "Mike")
......
......@@ -45,4 +45,8 @@ module SharedGroup
project.team << [user, :master]
@project_count += 1
end
def owned_group
@owned_group ||= Group.find_by(name: "Owned")
end
end
......@@ -9,6 +9,10 @@ module SharedUser
user_exists("Mary Jane", { username: "mary_jane" })
end
step 'gitlab user "Mike"' do
create(:user, name: "Mike")
end
protected
def user_exists(name, options = {})
......
......@@ -16,6 +16,17 @@ module Gitlab
def trigger(gl_id, oldrev, newrev, ref)
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(" ")
# function will return true if succesful
......@@ -54,6 +65,12 @@ module Gitlab
exit_status
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
......@@ -46,7 +46,7 @@ module Gitlab
end
def github_options
config["args"]["client_options"].deep_symbolize_keys
OmniAuth::Strategies::GitHub.default_options[:client_options].to_h.symbolize_keys
end
end
end
......
......@@ -75,7 +75,7 @@ module Gitlab
end
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
......
......@@ -60,8 +60,7 @@ module Gitlab
def url_for_label(project, label)
h = Gitlab::Application.routes.url_helpers
h.namespace_project_issues_path(project.namespace, project,
label_name: label.name,
only_path: context[:only_path])
label_name: label.name)
end
def render_colored_label(label)
......
......@@ -14,7 +14,7 @@ module Gitlab
def self.mute_mailer
code = <<-eos
def Notify.delay
def Notify.deliver_later
self
end
eos
......
......@@ -36,6 +36,11 @@ module Gitlab
@duration ||= started_at && finished_at ? finished_at - started_at : 0
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
@id
end
......
......@@ -114,24 +114,28 @@ server {
}
location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
}
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_page 418 = @gitlab-workhorse;
return 418;
}
location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
}
location ~ ^/api/v3/projects/.*/repository/archive {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
......@@ -139,16 +143,18 @@ server {
# Build artifacts should be submitted to this location
location ~ ^/[\w\.-]+/[\w\.-]+/builds/download {
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
}
# Build artifacts should be submitted to this location
location ~ /ci/api/v1/builds/[0-9]+/artifacts {
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
}
location @gitlab-workhorse {
......
......@@ -161,24 +161,28 @@ server {
}
location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
}
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_page 418 = @gitlab-workhorse;
return 418;
}
location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
}
location ~ ^/api/v3/projects/.*/repository/archive {
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
......@@ -186,16 +190,18 @@ server {
# Build artifacts should be submitted to this location
location ~ ^/[\w\.-]+/[\w\.-]+/builds/download {
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
}
# Build artifacts should be submitted to this location
location ~ /ci/api/v1/builds/[0-9]+/artifacts {
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
client_max_body_size 0;
# 'Error' 418 is a hack to re-use the @gitlab-workhorse block
error_page 418 = @gitlab-workhorse;
return 418;
}
location @gitlab-workhorse {
......
......@@ -2,16 +2,6 @@ module Gitlab
class TaskAbortedByUserError < StandardError; end
end
unless STDOUT.isatty
module Colored
extend self
def colorize(string, options={})
string
end
end
end
namespace :gitlab do
# Ask if the user wants to continue
......@@ -103,7 +93,7 @@ namespace :gitlab do
gitlab_user = Gitlab.config.gitlab.user
current_user = run(%W(whoami)).chomp
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 " Things may work\/fail for the wrong reasons."
puts " For correct results you should run this as user #{gitlab_user.magenta}."
......
#!/bin/bash
if [ -f /.dockerinit ]; then
wget -q http://ftp.de.debian.org/debian/pool/main/p/phantomjs/phantomjs_1.9.0-1+b1_amd64.deb
dpkg -i 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.8-0jessie_amd64.deb
apt-get update -qq
apt-get install -y -qq libicu-dev libkrb5-dev cmake nodejs postgresql-client mysql-client
......
......@@ -18,27 +18,31 @@ describe AbuseReportsController do
end
it "sends a notification email" do
post :create,
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
perform_enqueued_jobs do
post :create,
abuse_report: {
user_id: user.id,
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
......
......@@ -69,6 +69,21 @@ describe Projects::CommitController do
expect(response.body).to start_with("diff --git")
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
describe "as patch" do
......
......@@ -88,6 +88,22 @@ describe ProjectsController do
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
it "toggles star if user is signed in" do
sign_in(user)
......
......@@ -115,4 +115,119 @@ describe SnippetsController do
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
......@@ -87,13 +87,16 @@ describe "Admin::Users", feature: true do
end
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"
end
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')
email = ActionMailer::Base.deliveries.last
expect(email.subject).to have_content('Account was created')
......
......@@ -59,7 +59,7 @@ describe ApplicationHelper do
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).
to eq "<img alt=\"Banana sample\" src=\"#{avatar_url}\" />"
to eq "<img src=\"#{avatar_url}\" alt=\"Banana sample\" />"
end
it 'should give uploaded icon when present' do
......@@ -95,9 +95,9 @@ describe ApplicationHelper do
end
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
describe 'using a User' do
......@@ -150,15 +150,19 @@ describe ApplicationHelper do
stub_gravatar_setting(plain_url: 'http://example.local/?s=%{size}&hash=%{hash}')
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
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
it 'defaults size to 40 when given an invalid size' do
expect(helper.gravatar_icon(user_email, nil)).to include '?s=40'
it 'defaults size to 40@2x when given an invalid size' do
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
it 'ignores case and surrounding whitespace' do
......
......@@ -71,7 +71,7 @@ module Gitlab::Markdown
doc = filter("See #{reference}")
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
it 'links with adjacent text' do
......@@ -94,7 +94,7 @@ module Gitlab::Markdown
doc = filter("See #{reference}")
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'
end
......@@ -118,7 +118,7 @@ module Gitlab::Markdown
doc = filter("See #{reference}")
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'
end
......
......@@ -84,6 +84,19 @@ describe Gitlab::Sherlock::Transaction do
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
it 'returns the transaction ID' do
expect(transaction.to_param).to eq(transaction.id)
......
......@@ -77,6 +77,32 @@ describe Notify do
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
let(:example_site_path) { root_path }
let(:new_user) { create(:user, email: new_user_address, created_by_id: 1) }
......@@ -87,6 +113,7 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
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
is_expected.to have_body_text /Click here to set your password/
......@@ -115,6 +142,7 @@ describe Notify do
it_behaves_like 'an email sent from GitLab'
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
is_expected.not_to have_body_text /password/
......@@ -127,6 +155,7 @@ describe Notify do
subject { Notify.new_ssh_key_email(key.id) }
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
is_expected.to deliver_to key.user.email
......@@ -150,6 +179,8 @@ describe Notify do
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
is_expected.to deliver_to email.user.email
end
......@@ -194,6 +225,7 @@ describe Notify do
it_behaves_like 'an assignee email'
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
is_expected.to have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/
......@@ -207,6 +239,8 @@ describe Notify do
describe 'that are new with a description' do
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
is_expected.to have_body_text /#{issue_with_description.description}/
end
......@@ -217,6 +251,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email'
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
sender = subject.header[:from].addrs[0]
......@@ -246,6 +281,7 @@ describe Notify do
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 'it should show Gmail Actions View Issue link'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
......@@ -269,7 +305,6 @@ describe Notify do
is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
end
end
end
context 'for merge requests' do
......@@ -283,6 +318,7 @@ describe Notify do
it_behaves_like 'an assignee email'
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
is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
......@@ -326,6 +362,8 @@ describe Notify do
)
end
it_behaves_like 'it should show Gmail Actions View Merge request link'
it 'contains the description' do
is_expected.to have_body_text /#{merge_request_with_description.description}/
end
......@@ -336,6 +374,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email'
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
sender = subject.header[:from].addrs[0]
......@@ -365,6 +404,7 @@ describe Notify do
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 'it should show Gmail Actions View Merge request link'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
......@@ -394,6 +434,7 @@ describe Notify do
it_behaves_like 'a multiple recipients email'
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
sender = subject.header[:from].addrs[0]
......@@ -422,6 +463,7 @@ describe Notify do
subject { Notify.project_was_moved_email(project.id, user.id, "gitlab/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
is_expected.to have_subject /Project was moved/
......@@ -443,13 +485,16 @@ describe Notify do
subject { Notify.project_access_granted_email(project_member.id) }
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it 'has the correct subject' do
is_expected.to have_subject /Access to project was granted/
end
it 'contains name of project' do
is_expected.to have_body_text /#{project.name}/
end
it 'contains new user role' do
is_expected.to have_body_text /#{project_member.human_access}/
end
......@@ -464,6 +509,8 @@ describe Notify do
end
shared_examples 'a note email' do
it_behaves_like 'it should have Gmail Actions links'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(note_author.name)
......@@ -488,6 +535,7 @@ describe Notify do
it_behaves_like 'a note email'
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
is_expected.to have_subject /#{commit.title} \(#{commit.short_id}\)/
......@@ -507,6 +555,7 @@ describe Notify do
it_behaves_like 'a note email'
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
is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
......@@ -526,6 +575,7 @@ describe Notify do
it_behaves_like 'a note email'
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
is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
......@@ -546,6 +596,7 @@ describe Notify do
subject { Notify.group_access_granted_email(membership.id) }
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it 'has the correct subject' do
is_expected.to have_subject /Access to group was granted/
......@@ -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) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
......@@ -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) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
......@@ -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) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
......@@ -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) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
......@@ -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) }
it_behaves_like 'it should not have Gmail Actions links'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
......@@ -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) }
it_behaves_like 'it should show Gmail Actions View Commit link'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(user.name)
......
......@@ -44,13 +44,10 @@ describe Ci::MailService do
end
it do
should_email("git@example.com")
mail.execute(build)
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)
perform_enqueued_jobs do
expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
expect(ActionMailer::Base.deliveries.last.to).to eq(["git@example.com"])
end
end
end
......@@ -67,13 +64,10 @@ describe Ci::MailService do
end
it do
should_email("git@example.com")
mail.execute(build)
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)
perform_enqueued_jobs do
expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
expect(ActionMailer::Base.deliveries.last.to).to eq(["git@example.com"])
end
end
end
......@@ -95,14 +89,12 @@ describe Ci::MailService do
end
it do
should_email("git@example.com")
should_email("jeroen@example.com")
mail.execute(build)
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)
perform_enqueued_jobs do
expect{ mail.execute(build) }.to change{ ActionMailer::Base.deliveries.size }.by(2)
expect(
ActionMailer::Base.deliveries.map(&:to).flatten
).to include("git@example.com", "jeroen@example.com")
end
end
end
......@@ -124,14 +116,11 @@ describe Ci::MailService do
end
it do
should_email(commit.git_author_email)
should_email("jeroen@example.com")
mail.execute(build) if mail.can_execute?(build)
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)
perform_enqueued_jobs do
expect do
mail.execute(build) if mail.can_execute?(build)
end.to_not change{ ActionMailer::Base.deliveries.size }
end
end
end
......@@ -177,14 +166,11 @@ describe Ci::MailService do
it do
Ci::Build.retry(build)
should_email(commit.git_author_email)
should_email("jeroen@example.com")
mail.execute(build) if mail.can_execute?(build)
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)
perform_enqueued_jobs do
expect do
mail.execute(build) if mail.can_execute?(build)
end.to_not change{ ActionMailer::Base.deliveries.size }
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
end
it 'should be prepopulated with the settings' do
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[:new_issue_url]).to eq("http://jira.sample/projects/project_a/issues/new")
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["new_issue_url"]).to eq("http://jira.sample/projects/project_a/issues/new")
end
end
end
......
......@@ -14,7 +14,9 @@ describe Issues::CloseService do
describe :execute do
context "valid params" 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
it { expect(@issue).to be_valid }
......
......@@ -36,7 +36,10 @@ describe Issues::UpdateService do
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
end
......
......@@ -18,7 +18,9 @@ describe MergeRequests::CloseService do
before do
allow(service).to receive(:execute_hooks)
@merge_request = service.execute(merge_request)
perform_enqueued_jobs do
@merge_request = service.execute(merge_request)
end
end
it { expect(@merge_request).to be_valid }
......
......@@ -17,8 +17,9 @@ describe MergeRequests::MergeService do
before do
allow(service).to receive(:execute_hooks)
service.execute(merge_request, 'Awesome message')
perform_enqueued_jobs do
service.execute(merge_request, 'Awesome message')
end
end
it { expect(merge_request).to be_valid }
......
......@@ -19,7 +19,9 @@ describe MergeRequests::ReopenService do
allow(service).to receive(:execute_hooks)
merge_request.state = :closed
service.execute(merge_request)
perform_enqueued_jobs do
service.execute(merge_request)
end
end
it { expect(merge_request).to be_valid }
......
......@@ -42,8 +42,10 @@ describe MergeRequests::UpdateService do
before do
allow(service).to receive(:execute_hooks)
@merge_request = service.execute(merge_request)
@merge_request.reload
perform_enqueued_jobs do
@merge_request = service.execute(merge_request)
@merge_request.reload
end
end
it { expect(@merge_request).to be_valid }
......
......@@ -3,6 +3,12 @@ require 'spec_helper'
describe NotificationService do
let(:notification) { NotificationService.new }
around(:each) do |example|
perform_enqueued_jobs do
example.run
end
end
describe 'Keys' do
describe :new_key do
let!(:key) { create(:personal_key) }
......@@ -10,8 +16,7 @@ describe NotificationService do
it { expect(notification.new_key(key)).to be_truthy }
it 'should sent email to key owner' do
expect(Notify).to receive(:new_ssh_key_email).with(key.id)
notification.new_key(key)
expect{ notification.new_key(key) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
end
end
end
......@@ -23,8 +28,7 @@ describe NotificationService do
it { expect(notification.new_email(email)).to be_truthy }
it 'should send email to email owner' do
expect(Notify).to receive(:new_email_email).with(email.id)
notification.new_email(email)
expect{ notification.new_email(email) }.to change{ ActionMailer::Base.deliveries.size }.by(1)
end
end
end
......@@ -47,18 +51,20 @@ describe NotificationService do
it do
add_users_with_subscription(note.project, issue)
should_email(@u_watcher.id)
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)
ActionMailer::Base.deliveries.clear
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
it 'filters out "mentioned in" notes' do
......@@ -82,26 +88,20 @@ describe NotificationService do
group_member = note.project.group.group_members.find_by_user_id(@u_watcher.id)
group_member.notification_level = Notification::N_GLOBAL
group_member.save
ActionMailer::Base.deliveries.clear
end
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)
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)
should_email(note.noteable.author)
should_email(note.noteable.assignee)
should_email(@u_mentioned)
should_not_email(@u_watcher)
should_not_email(note.author)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end
end
end
......@@ -113,24 +113,26 @@ describe NotificationService do
before do
build_team(note.project)
ActionMailer::Base.deliveries.clear
end
describe :new_note do
it do
notification.new_note(note)
# Notify all team members
note.project.team.members.each do |member|
# User with disabled notification should not be notified
next if member.id == @u_disabled.id
should_email(member.id)
should_email(member)
end
should_email(note.noteable.author_id)
should_email(note.noteable.assignee_id)
should_not_email(note.author_id)
should_not_email(@u_mentioned.id)
should_not_email(@u_disabled.id)
should_not_email(@u_not_mentioned.id)
notification.new_note(note)
should_email(note.noteable.author)
should_email(note.noteable.assignee)
should_not_email(note.author)
should_email(@u_mentioned)
should_not_email(@u_disabled)
should_email(@u_not_mentioned)
end
it 'filters out "mentioned in" notes' do
......@@ -140,14 +142,6 @@ describe NotificationService do
notification.new_note(mentioned_note)
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
context 'commit note' do
......@@ -156,43 +150,38 @@ describe NotificationService do
before do
build_team(note.project)
ActionMailer::Base.deliveries.clear
allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer)
end
describe :new_note do
describe :new_note, :perform_enqueued_jobs 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)
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
it do
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)
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
it do
@u_committer.update_attributes(notification_level: Notification::N_MENTION)
should_not_email(@u_committer.id, note)
notification.new_note(note)
end
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)
should_not_email(@u_committer)
end
end
end
......@@ -205,99 +194,69 @@ describe NotificationService do
before do
build_team(issue.project)
add_users_with_subscription(issue.project, issue)
ActionMailer::Base.deliveries.clear
end
describe :new_issue 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)
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
it do
issue.assignee.update_attributes(notification_level: Notification::N_MENTION)
should_not_email(issue.assignee_id)
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)
expect(Notify).not_to receive(:new_issue_email).with(user_id, issue.id)
should_not_email(issue.assignee)
end
end
describe :reassigned_issue 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)
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)
expect(Notify).not_to receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id)
should_email(issue.assignee)
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
describe :close_issue 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)
end
def should_email(user_id)
expect(Notify).to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id)
end
def should_not_email(user_id)
expect(Notify).not_to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id)
should_email(issue.assignee)
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)
should_not_email(@u_disabled)
end
end
describe :reopen_issue 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)
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)
expect(Notify).not_to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id)
should_email(issue.assignee)
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
......@@ -309,108 +268,74 @@ describe NotificationService do
before do
build_team(merge_request.target_project)
add_users_with_subscription(merge_request.target_project, merge_request)
ActionMailer::Base.deliveries.clear
end
describe :new_merge_request 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)
end
def should_email(user_id)
expect(Notify).to receive(:new_merge_request_email).with(user_id, merge_request.id)
end
def should_not_email(user_id)
expect(Notify).not_to receive(:new_merge_request_email).with(user_id, merge_request.id)
should_email(merge_request.assignee)
should_email(@u_watcher)
should_email(@u_participant_mentioned)
should_not_email(@u_participating)
should_not_email(@u_disabled)
end
end
describe :reassigned_merge_request 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)
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)
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(merge_request.assignee)
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
describe :closed_merge_request 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)
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)
expect(Notify).not_to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
should_email(merge_request.assignee)
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
describe :merged_merge_request 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)
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)
expect(Notify).not_to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
should_email(merge_request.assignee)
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
describe :reopen_merge_request 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)
end
def should_email(user_id)
expect(Notify).to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id)
end
def should_not_email(user_id)
expect(Notify).not_to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id)
should_email(merge_request.assignee)
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
......@@ -420,22 +345,16 @@ describe NotificationService do
before do
build_team(project)
ActionMailer::Base.deliveries.clear
end
describe :project_was_moved 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")
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)
expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab")
should_email(@u_watcher)
should_email(@u_participating)
should_not_email(@u_disabled)
end
end
end
......@@ -469,4 +388,18 @@ describe NotificationService do
issuable.subscriptions.create(user: @subscriber, subscribed: true)
issuable.subscriptions.create(user: @unsubscriber, subscribed: false)
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
......@@ -31,6 +31,7 @@ RSpec.configure do |config|
config.include StubConfiguration
config.include RelativeUrl, type: feature
config.include TestEnv
config.include ActiveJob::TestHelper
config.include StubGitlabCalls
config.include StubGitlabData
config.include BenchmarkMatchers, benchmark: true
......
......@@ -21,12 +21,14 @@ describe EmailReceiverWorker do
end
it "sends out a rejection email" do
described_class.new.perform(raw_message)
email = ActionMailer::Base.deliveries.last
expect(email).not_to be_nil
expect(email.to).to eq(["jake@adventuretime.ooo"])
expect(email.subject).to include("Rejected")
perform_enqueued_jobs do
described_class.new.perform(raw_message)
email = ActionMailer::Base.deliveries.last
expect(email).not_to be_nil
expect(email.to).to eq(["jake@adventuretime.ooo"])
expect(email.subject).to include("Rejected")
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