diff --git a/CHANGELOG b/CHANGELOG
index 12e00040094834bc8356c79627821d7152a9e756..07ff3d6de4220bb4d3d5d965d516014f258dd90f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,12 @@
 Please view this file on the master branch, on stable branches it's out of date.
 
 v 8.1.0 (unreleased)
+  - Make diff file view easier to use on mobile screens (Stan Hu)
+  - Add support for creating directories from Files page (Stan Hu)
+  - Allow removing of project without confirmation when JavaScript is disabled (Stan Hu)
+  - Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu)
+  - Improved performance of the trending projects page
+  - Improved performance of finding projects by their namespace
   - Fix bug where transferring a project would result in stale commit links (Stan Hu)
   - Include full path of source and target branch names in New Merge Request page (Stan Hu)
   - Add user preference to view activities as default dashboard (Stan Hu)
@@ -10,7 +16,9 @@ v 8.1.0 (unreleased)
   - Move CI charts to project graphs area
   - Fix cases where Markdown did not render links in activity feed (Stan Hu)
   - Add first and last to pagination (Zeger-Jan van de Weg)
+  - Added Commit Status API
   - Show CI status on commit page
+  - Added CI_BUILD_TAG, _STAGE, _NAME and _TRIGGERED to CI builds
   - Show CI status on Your projects page and Starred projects page
   - Remove "Continuous Integration" page from dashboard
   - Add notes and SSL verification entries to hook APIs (Ben Boeckel)
@@ -20,6 +28,7 @@ v 8.1.0 (unreleased)
   - Move CI triggers page to project settings area
   - Move CI project settings page to CE project settings area
   - Fix bug when removed file was not appearing in merge request diff
+  - Show warning when build cannot be served by any of the available CI runners
   - Note the original location of a moved project when notifying users of the move
   - Improve error message when merging fails
   - Add support of multibyte characters in LDAP UID (Roman Petrov)
@@ -31,6 +40,22 @@ v 8.1.0 (unreleased)
   - Move CI web hooks page to project settings area
   - Fix User Identities API. It now allows you to properly create or update user's identities.
   - Add user preference to change layout width (Peter Göbel)
+  - Use commit status in merge request widget as preffered source of CI status
+  - Integrate CI commit and build pages into project pages
+  - Move CI services page to project settings area
+  - Add "Quick Submit" behavior to input fields throughout the application. Use
+    Cmd+Enter on Mac and Ctrl+Enter on Windows/Linux.
+  - Fix position of hamburger in header for smaller screens (Han Loong Liauw)
+  - Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji)
+  - Persist filters when sorting on admin user page (Jerry Lukins)
+  - Add spellcheck=false to certain input fields
+  - Invalidate stored service password if the endpoint URL is changed
+  - Project names are not fully shown if group name is too big, even on group page view
+  - Apply new design for Files page
+  - Add "New Page" button to Wiki Pages tab (Stan Hu)
+  - Only render 404 page from /public
+  - Hide passwords from services API (Alex Lossent)
+  - Fix: Images cannot show when projects' path was changed
 
 v 8.0.4
   - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu)
@@ -38,11 +63,14 @@ v 8.0.4
   - Fix anchors to comments in diffs
   - Remove CI token from build traces
   - Fix "Assign All" button on Runner admin page
+  - Fix search in Files
+  - Add full project namespace to payload of system webhooks (Ricardo Band)
 
 v 8.0.3
   - Fix URL shown in Slack notifications
   - Fix bug where projects would appear to be stuck in the forked import state (Stan Hu)
   - Fix Error 500 in creating merge requests with > 1000 diffs (Stan Hu)
+  - Add work_in_progress key to MR web hooks (Ben Boeckel)
 
 v 8.0.2
   - Fix default avatar not rendering in network graph (Stan Hu)
diff --git a/Gemfile b/Gemfile
index d81cc4d540a87c89b0a6f38590145ffb4f36bc37..567211cd9c00465af86ad5340f20ffd7304c56fb 100644
--- a/Gemfile
+++ b/Gemfile
@@ -22,20 +22,20 @@ gem "mysql2", '~> 0.3.16', group: :mysql
 gem "pg", '~> 0.18.2', group: :postgres
 
 # Authentication libraries
-gem "devise", '~> 3.5.2'
-gem "devise-async", '~> 0.9.0'
-gem 'omniauth', "~> 1.2.2"
-gem 'omniauth-google-oauth2', '~> 0.2.5'
-gem 'omniauth-twitter', '~> 1.0.1'
-gem 'omniauth-github', '~> 1.1.1'
-gem 'omniauth-shibboleth', '~> 1.1.1'
-gem 'omniauth-kerberos', '~> 0.2.0', group: :kerberos
-gem 'omniauth-gitlab', '~> 1.0.0'
-gem 'omniauth-bitbucket', '~> 0.0.2'
-gem 'omniauth-saml', '~> 1.4.0'
-gem 'doorkeeper', '~> 2.1.3'
+gem 'devise',                 '~> 3.5.2'
+gem 'devise-async',           '~> 0.9.0'
+gem 'doorkeeper',             '~> 2.1.3'
+gem 'omniauth',               '~> 1.2.2'
+gem 'omniauth-bitbucket',     '~> 0.0.2'
+gem 'omniauth-github',        '~> 1.1.1'
+gem 'omniauth-gitlab',        '~> 1.0.0'
+gem 'omniauth-google-oauth2', '~> 0.2.0'
+gem 'omniauth-kerberos',      '~> 0.3.0', group: :kerberos
+gem 'omniauth-saml',          '~> 1.4.0'
+gem 'omniauth-shibboleth',    '~> 1.2.0'
+gem 'omniauth-twitter',       '~> 1.2.0'
 gem 'omniauth_crowd'
-gem "rack-oauth2", "~> 1.0.5"
+gem 'rack-oauth2',            '~> 1.0.5'
 
 # Two-factor authentication
 gem 'devise-two-factor', '~> 2.0.0'
@@ -65,9 +65,9 @@ gem 'gollum-lib', '~> 4.0.2'
 gem "gitlab-linguist", "~> 3.0.1", require: "linguist"
 
 # API
-gem "grape", "~> 0.6.1"
-gem "grape-entity", "~> 0.4.2"
-gem 'rack-cors', '~> 0.2.9', require: 'rack/cors'
+gem 'grape',        '~> 0.6.1'
+gem 'grape-entity', '~> 0.4.2'
+gem 'rack-cors',    '~> 0.4.0', require: 'rack/cors'
 
 # Format dates and times
 # based on human-friendly examples
@@ -80,7 +80,7 @@ gem 'enumerize', '~> 0.7.0'
 gem "kaminari", "~> 0.16.3"
 
 # HAML
-gem "haml-rails", '~> 0.5.3'
+gem "haml-rails", '~> 0.9.0'
 
 # Files attachments
 gem "carrierwave", '~> 0.9.0'
@@ -128,7 +128,6 @@ gem 'after_commit_queue'
 gem 'acts-as-taggable-on', '~> 3.4'
 
 # Background jobs
-gem 'slim', '~> 2.0.2'
 gem 'sinatra', '~> 1.4.4', require: nil
 gem 'sidekiq', '3.3.0'
 gem 'sidetiq', '~> 0.6.3'
@@ -151,7 +150,7 @@ gem 'version_sorter', '~> 2.0.0'
 gem "redis-rails", '~> 4.0.0'
 
 # Campfire integration
-gem 'tinder', '~> 1.9.2'
+gem 'tinder', '~> 1.10.0'
 
 # HipChat integration
 gem 'hipchat', '~> 1.5.0'
@@ -163,7 +162,7 @@ gem "gitlab-flowdock-git-hook", "~> 1.0.1"
 gem "gemnasium-gitlab-service", "~> 0.2"
 
 # Slack integration
-gem "slack-notifier", "~> 1.0.0"
+gem "slack-notifier", "~> 1.2.0"
 
 # Asana integration
 gem 'asana', '~> 0.0.6'
@@ -291,7 +290,7 @@ gem 'newrelic-grape'
 
 gem 'octokit', '~> 3.7.0'
 
-gem "mail_room", "~> 0.5.2"
+gem "mail_room", "~> 0.6.0"
 
 gem 'email_reply_parser', '~> 0.5.8'
 
@@ -300,9 +299,6 @@ gem 'activerecord-deprecated_finders', '~> 1.0.3'
 gem 'activerecord-session_store', '~> 0.1.0'
 gem "nested_form", '~> 0.3.2'
 
-# Scheduled
-gem 'whenever', '~> 0.8.4', require: false
-
 # OAuth
 gem 'oauth2', '~> 1.0.0'
 
diff --git a/Gemfile.lock b/Gemfile.lock
index f9421331e4e951995cc6d7efc9849f2351506b84..b06d3f37ed00d6de7389ba3a68f3eccc9ad7e7cf 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -105,7 +105,6 @@ GEM
     celluloid (0.16.0)
       timers (~> 4.0.0)
     charlock_holmes (0.6.9.4)
-    chronic (0.10.2)
     chunky_png (1.3.4)
     cliver (0.3.2)
     coderay (1.1.0)
@@ -182,8 +181,8 @@ GEM
     factory_girl_rails (4.3.0)
       factory_girl (~> 4.3.0)
       railties (>= 3.0.0)
-    faraday (0.8.10)
-      multipart-post (~> 1.2.0)
+    faraday (0.9.2)
+      multipart-post (>= 1.2, < 3)
     faraday_middleware (0.10.0)
       faraday (>= 0.7.4, < 0.10)
     fastercsv (1.5.5)
@@ -330,12 +329,13 @@ GEM
       rspec (>= 2.14, < 4.0)
     haml (4.0.7)
       tilt
-    haml-rails (0.5.3)
+    haml-rails (0.9.0)
       actionpack (>= 4.0.1)
       activesupport (>= 4.0.1)
-      haml (>= 3.1, < 5.0)
+      haml (>= 4.0.6, < 5.0)
+      html2haml (>= 1.0.1)
       railties (>= 4.0.1)
-    hashie (2.1.2)
+    hashie (3.4.2)
     highline (1.6.21)
     hike (1.2.3)
     hipchat (1.5.2)
@@ -345,6 +345,11 @@ GEM
     html-pipeline (1.11.0)
       activesupport (>= 2)
       nokogiri (~> 1.4)
+    html2haml (2.0.0)
+      erubis (~> 2.7.0)
+      haml (~> 4.0.0)
+      nokogiri (~> 1.6.0)
+      ruby_parser (~> 3.5)
     http-cookie (1.0.2)
       domain_name (~> 0.5)
     http_parser.rb (0.5.3)
@@ -387,7 +392,7 @@ GEM
       systemu (~> 2.6.2)
     mail (2.6.3)
       mime-types (>= 1.16, < 3)
-    mail_room (0.5.2)
+    mail_room (0.6.0)
     method_source (0.8.2)
     mime-types (1.25.1)
     mimemagic (0.3.0)
@@ -396,7 +401,7 @@ GEM
     mousetrap-rails (1.4.6)
     multi_json (1.11.2)
     multi_xml (0.5.5)
-    multipart-post (1.2.0)
+    multipart-post (2.0.0)
     mysql2 (0.3.20)
     nenv (0.2.0)
     nested_form (0.3.2)
@@ -440,7 +445,7 @@ GEM
     omniauth-google-oauth2 (0.2.6)
       omniauth (> 1.0)
       omniauth-oauth2 (~> 1.1)
-    omniauth-kerberos (0.2.0)
+    omniauth-kerberos (0.3.0)
       omniauth-multipassword
       timfel-krb5-auth (~> 0.8)
     omniauth-multipassword (0.4.2)
@@ -454,11 +459,11 @@ GEM
     omniauth-saml (1.4.1)
       omniauth (~> 1.1)
       ruby-saml (~> 1.0.0)
-    omniauth-shibboleth (1.1.2)
+    omniauth-shibboleth (1.2.1)
       omniauth (>= 1.0.0)
-    omniauth-twitter (1.0.1)
-      multi_json (~> 1.3)
-      omniauth-oauth (~> 1.0)
+    omniauth-twitter (1.2.1)
+      json (~> 1.3)
+      omniauth-oauth (~> 1.1)
     omniauth_crowd (2.2.3)
       activesupport
       nokogiri (>= 1.4.4)
@@ -496,7 +501,7 @@ GEM
       rack (>= 0.4)
     rack-attack (4.3.0)
       rack
-    rack-cors (0.2.9)
+    rack-cors (0.4.0)
     rack-mini-profiler (0.9.7)
       rack (>= 1.1.3)
     rack-mount (0.8.3)
@@ -666,10 +671,7 @@ GEM
       rack-protection (~> 1.4)
       tilt (>= 1.3, < 3)
     six (0.2.0)
-    slack-notifier (1.0.0)
-    slim (2.0.3)
-      temple (~> 0.6.6)
-      tilt (>= 1.3.3, < 2.1)
+    slack-notifier (1.2.1)
     slop (3.6.0)
     spinach (0.8.10)
       colorize
@@ -705,7 +707,6 @@ GEM
       railties (>= 3.2.5, < 5)
     teaspoon-jasmine (2.2.0)
       teaspoon (>= 1.0.0)
-    temple (0.6.10)
     term-ansicolor (1.3.2)
       tins (~> 1.0)
     terminal-table (1.5.2)
@@ -721,13 +722,13 @@ GEM
     timers (4.0.4)
       hitimes
     timfel-krb5-auth (0.8.3)
-    tinder (1.9.4)
+    tinder (1.10.1)
       eventmachine (~> 1.0)
-      faraday (~> 0.8.9)
+      faraday (~> 0.9.0)
       faraday_middleware (~> 0.9)
-      hashie (>= 1.0, < 3)
+      hashie (>= 1.0)
       json (~> 1.8.0)
-      mime-types (~> 1.19)
+      mime-types
       multi_json (~> 1.7)
       twitter-stream (~> 0.1)
     tins (1.6.0)
@@ -770,9 +771,6 @@ GEM
     websocket-driver (0.6.2)
       websocket-extensions (>= 0.1.0)
     websocket-extensions (0.1.2)
-    whenever (0.8.4)
-      activesupport (>= 2.3.4)
-      chronic (>= 0.6.3)
     wikicloth (0.8.1)
       builder
       expression_parser
@@ -845,7 +843,7 @@ DEPENDENCIES
   grape-entity (~> 0.4.2)
   growl
   guard-rspec (~> 4.2.0)
-  haml-rails (~> 0.5.3)
+  haml-rails (~> 0.9.0)
   hipchat (~> 1.5.0)
   html-pipeline (~> 1.11.0)
   httparty (~> 0.13.3)
@@ -856,7 +854,7 @@ DEPENDENCIES
   jquery-ui-rails (~> 4.2.1)
   kaminari (~> 0.16.3)
   letter_opener (~> 1.1.2)
-  mail_room (~> 0.5.2)
+  mail_room (~> 0.6.0)
   minitest (~> 5.7.0)
   mousetrap-rails (~> 1.4.6)
   mysql2 (~> 0.3.16)
@@ -870,11 +868,11 @@ DEPENDENCIES
   omniauth-bitbucket (~> 0.0.2)
   omniauth-github (~> 1.1.1)
   omniauth-gitlab (~> 1.0.0)
-  omniauth-google-oauth2 (~> 0.2.5)
-  omniauth-kerberos (~> 0.2.0)
+  omniauth-google-oauth2 (~> 0.2.0)
+  omniauth-kerberos (~> 0.3.0)
   omniauth-saml (~> 1.4.0)
-  omniauth-shibboleth (~> 1.1.1)
-  omniauth-twitter (~> 1.0.1)
+  omniauth-shibboleth (~> 1.2.0)
+  omniauth-twitter (~> 1.2.0)
   omniauth_crowd
   org-ruby (~> 0.9.12)
   paranoia (~> 2.0)
@@ -883,7 +881,7 @@ DEPENDENCIES
   pry-rails
   quiet_assets (~> 1.0.2)
   rack-attack (~> 4.3.0)
-  rack-cors (~> 0.2.9)
+  rack-cors (~> 0.4.0)
   rack-mini-profiler (~> 0.9.0)
   rack-oauth2 (~> 1.0.5)
   rails (= 4.1.12)
@@ -912,8 +910,7 @@ DEPENDENCIES
   simplecov (~> 0.10.0)
   sinatra (~> 1.4.4)
   six (~> 0.2.0)
-  slack-notifier (~> 1.0.0)
-  slim (~> 2.0.2)
+  slack-notifier (~> 1.2.0)
   spinach-rails (~> 0.2.1)
   spring (~> 1.3.6)
   spring-commands-rspec (~> 1.0.4)
@@ -927,7 +924,7 @@ DEPENDENCIES
   teaspoon-jasmine (~> 2.2.0)
   test_after_commit (~> 0.2.2)
   thin (~> 1.6.1)
-  tinder (~> 1.9.2)
+  tinder (~> 1.10.0)
   turbolinks (~> 2.5.0)
   uglifier (~> 2.3.2)
   underscore-rails (~> 1.4.4)
@@ -937,7 +934,6 @@ DEPENDENCIES
   version_sorter (~> 2.0.0)
   virtus (~> 1.0.1)
   webmock (~> 1.21.0)
-  whenever (~> 0.8.4)
   wikicloth (= 0.8.1)
 
 BUNDLED WITH
diff --git a/PROCESS.md b/PROCESS.md
index 1b6b3e7d32d053ac6124be3c1637b3f8db12c204..9f4b708d2b56b1c558e93e361284c802f707cba5 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -79,7 +79,11 @@ Thanks for the issue report but we only support issues for the latest stable ver
 
 ### Support requests and configuration questions
 
-Thanks for your interest in GitLab. We don't use the issue tracker for support requests and configuration questions. Please use the \[support forum\]\(https://groups.google.com/forum/#!forum/gitlabhq), \[Stack Overflow\]\(http://stackoverflow.com/questions/tagged/gitlab), the #gitlab IRC channel on Freenode or the http://about.gitlab.com paid services for this purpose. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
+Thanks for your interest in GitLab. We don't use the issue tracker for support
+requests and configuration questions. Please check our
+\[getting help\]\(https://about.gitlab.com/getting-help/) page to see all of the available
+support options. Also, have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md)
+for more information.
 
 ### Code format
 
diff --git a/README.md b/README.md
index 91855b42d29968adf8c0e1cc4b56030f949b159e..52e2d9776208e95b7d5c11bcfc7f2fe63fcab34c 100644
--- a/README.md
+++ b/README.md
@@ -71,7 +71,7 @@ GitLab is a Ruby on Rails application that runs on the following software:
 - Ubuntu/Debian/CentOS/RHEL
 - Ruby (MRI) 2.1
 - Git 1.7.10+
-- Redis 2.0+
+- Redis 2.4+
 - MySQL or PostgreSQL
 
 For more information please see the [architecture documentation](http://doc.gitlab.com/ce/development/architecture.html).
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 8e987ac4e83ee5fb34299fc33af6d8c784f3a362..945ffb660e66783325f44014185f1604b502c480 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -180,6 +180,7 @@ $ ->
   $('.navbar-toggle').on 'click', ->
     $('.header-content .title').toggle()
     $('.header-content .navbar-collapse').toggle()
+    $('.navbar-toggle').toggleClass('active')
 
   # Show/hide comments on diff
   $("body").on "click", ".js-toggle-diff-comments", (e) ->
diff --git a/app/assets/javascripts/behaviors/quick_submit.js.coffee b/app/assets/javascripts/behaviors/quick_submit.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..4ec8531d58027a532df183a42c02aa70cfb10b53
--- /dev/null
+++ b/app/assets/javascripts/behaviors/quick_submit.js.coffee
@@ -0,0 +1,29 @@
+# Quick Submit behavior
+#
+# When an input field with the `js-quick-submit` class receives a "Meta+Enter"
+# (Mac) or "Ctrl+Enter" (Linux/Windows) key combination, its parent form is
+# submitted.
+#
+#= require extensions/jquery
+#
+# ### Example Markup
+#
+#   <form action="/foo">
+#     <input type="text" class="js-quick-submit" />
+#     <textarea class="js-quick-submit"></textarea>
+#   </form>
+#
+$(document).on 'keydown.quick_submit', '.js-quick-submit', (e) ->
+  return if (e.originalEvent && e.originalEvent.repeat) || e.repeat
+  return unless e.keyCode == 13 # Enter
+
+  if navigator.userAgent.match(/Macintosh/)
+    return unless (e.metaKey && !e.altKey && !e.ctrlKey && !e.shiftKey)
+  else
+    return unless (e.ctrlKey && !e.altKey && !e.metaKey && !e.shiftKey)
+
+  e.preventDefault()
+
+  $form = $(e.target).closest('form')
+  $form.find('input[type=submit], button[type=submit]').disable()
+  $form.submit()
diff --git a/app/assets/javascripts/behaviors/requires_input.js.coffee b/app/assets/javascripts/behaviors/requires_input.js.coffee
index 8318fe435b3911f5ca44d8b4597e8e675a1ab65d..79d750d1847730a401af9b20ab576fc15064c657 100644
--- a/app/assets/javascripts/behaviors/requires_input.js.coffee
+++ b/app/assets/javascripts/behaviors/requires_input.js.coffee
@@ -34,6 +34,5 @@ $.fn.requiresInput = ->
 
   $form.on 'change input', fieldSelector, requireInput
 
-# Triggered on standard document `ready` and on Turbolinks `page:load` events
-$(document).on 'ready page:load', ->
+$ ->
   $('form.js-requires-input').requiresInput()
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee
index 3ab3ba66754a9d3cb4400cbb68998c316145f190..5b604adbbb1bca76236caaee1f5395f6cb7f4059 100644
--- a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee
+++ b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee
@@ -47,6 +47,7 @@ class @BlobFileDropzone
           return
 
         this.on 'sending', (file, xhr, formData) ->
+          formData.append('new_branch', form.find('#new_branch').val())
           formData.append('commit_message', form.find('#commit_message').val())
           return
 
diff --git a/app/assets/javascripts/ci/Chart.min.js b/app/assets/javascripts/ci/Chart.min.js
deleted file mode 100644
index ab63588108763378ebc76ea1bb73191a70d70b12..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/ci/Chart.min.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var Chart=function(s){function v(a,c,b){a=A((a-c.graphMin)/(c.steps*c.stepValue),1,0);return b*c.steps*a}function x(a,c,b,e){function h(){g+=f;var k=a.animation?A(d(g),null,0):1;e.clearRect(0,0,q,u);a.scaleOverlay?(b(k),c()):(c(),b(k));if(1>=g)D(h);else if("function"==typeof a.onAnimationComplete)a.onAnimationComplete()}var f=a.animation?1/A(a.animationSteps,Number.MAX_VALUE,1):1,d=B[a.animationEasing],g=a.animation?0:1;"function"!==typeof c&&(c=function(){});D(h)}function C(a,c,b,e,h,f){var d;a=
-Math.floor(Math.log(e-h)/Math.LN10);h=Math.floor(h/(1*Math.pow(10,a)))*Math.pow(10,a);e=Math.ceil(e/(1*Math.pow(10,a)))*Math.pow(10,a)-h;a=Math.pow(10,a);for(d=Math.round(e/a);d<b||d>c;)a=d<b?a/2:2*a,d=Math.round(e/a);c=[];z(f,c,d,h,a);return{steps:d,stepValue:a,graphMin:h,labels:c}}function z(a,c,b,e,h){if(a)for(var f=1;f<b+1;f++)c.push(E(a,{value:(e+h*f).toFixed(0!=h%1?h.toString().split(".")[1].length:0)}))}function A(a,c,b){return!isNaN(parseFloat(c))&&isFinite(c)&&a>c?c:!isNaN(parseFloat(b))&&
-isFinite(b)&&a<b?b:a}function y(a,c){var b={},e;for(e in a)b[e]=a[e];for(e in c)b[e]=c[e];return b}function E(a,c){var b=!/\W/.test(a)?F[a]=F[a]||E(document.getElementById(a).innerHTML):new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+a.replace(/[\r\t\n]/g," ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');");return c?
-b(c):b}var r=this,B={linear:function(a){return a},easeInQuad:function(a){return a*a},easeOutQuad:function(a){return-1*a*(a-2)},easeInOutQuad:function(a){return 1>(a/=0.5)?0.5*a*a:-0.5*(--a*(a-2)-1)},easeInCubic:function(a){return a*a*a},easeOutCubic:function(a){return 1*((a=a/1-1)*a*a+1)},easeInOutCubic:function(a){return 1>(a/=0.5)?0.5*a*a*a:0.5*((a-=2)*a*a+2)},easeInQuart:function(a){return a*a*a*a},easeOutQuart:function(a){return-1*((a=a/1-1)*a*a*a-1)},easeInOutQuart:function(a){return 1>(a/=0.5)?
-0.5*a*a*a*a:-0.5*((a-=2)*a*a*a-2)},easeInQuint:function(a){return 1*(a/=1)*a*a*a*a},easeOutQuint:function(a){return 1*((a=a/1-1)*a*a*a*a+1)},easeInOutQuint:function(a){return 1>(a/=0.5)?0.5*a*a*a*a*a:0.5*((a-=2)*a*a*a*a+2)},easeInSine:function(a){return-1*Math.cos(a/1*(Math.PI/2))+1},easeOutSine:function(a){return 1*Math.sin(a/1*(Math.PI/2))},easeInOutSine:function(a){return-0.5*(Math.cos(Math.PI*a/1)-1)},easeInExpo:function(a){return 0==a?1:1*Math.pow(2,10*(a/1-1))},easeOutExpo:function(a){return 1==
-a?1:1*(-Math.pow(2,-10*a/1)+1)},easeInOutExpo:function(a){return 0==a?0:1==a?1:1>(a/=0.5)?0.5*Math.pow(2,10*(a-1)):0.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return 1<=a?a:-1*(Math.sqrt(1-(a/=1)*a)-1)},easeOutCirc:function(a){return 1*Math.sqrt(1-(a=a/1-1)*a)},easeInOutCirc:function(a){return 1>(a/=0.5)?-0.5*(Math.sqrt(1-a*a)-1):0.5*(Math.sqrt(1-(a-=2)*a)+1)},easeInElastic:function(a){var c=1.70158,b=0,e=1;if(0==a)return 0;if(1==(a/=1))return 1;b||(b=0.3);e<Math.abs(1)?(e=1,c=b/4):c=b/(2*
-Math.PI)*Math.asin(1/e);return-(e*Math.pow(2,10*(a-=1))*Math.sin((1*a-c)*2*Math.PI/b))},easeOutElastic:function(a){var c=1.70158,b=0,e=1;if(0==a)return 0;if(1==(a/=1))return 1;b||(b=0.3);e<Math.abs(1)?(e=1,c=b/4):c=b/(2*Math.PI)*Math.asin(1/e);return e*Math.pow(2,-10*a)*Math.sin((1*a-c)*2*Math.PI/b)+1},easeInOutElastic:function(a){var c=1.70158,b=0,e=1;if(0==a)return 0;if(2==(a/=0.5))return 1;b||(b=1*0.3*1.5);e<Math.abs(1)?(e=1,c=b/4):c=b/(2*Math.PI)*Math.asin(1/e);return 1>a?-0.5*e*Math.pow(2,10*
-(a-=1))*Math.sin((1*a-c)*2*Math.PI/b):0.5*e*Math.pow(2,-10*(a-=1))*Math.sin((1*a-c)*2*Math.PI/b)+1},easeInBack:function(a){return 1*(a/=1)*a*(2.70158*a-1.70158)},easeOutBack:function(a){return 1*((a=a/1-1)*a*(2.70158*a+1.70158)+1)},easeInOutBack:function(a){var c=1.70158;return 1>(a/=0.5)?0.5*a*a*(((c*=1.525)+1)*a-c):0.5*((a-=2)*a*(((c*=1.525)+1)*a+c)+2)},easeInBounce:function(a){return 1-B.easeOutBounce(1-a)},easeOutBounce:function(a){return(a/=1)<1/2.75?1*7.5625*a*a:a<2/2.75?1*(7.5625*(a-=1.5/2.75)*
-a+0.75):a<2.5/2.75?1*(7.5625*(a-=2.25/2.75)*a+0.9375):1*(7.5625*(a-=2.625/2.75)*a+0.984375)},easeInOutBounce:function(a){return 0.5>a?0.5*B.easeInBounce(2*a):0.5*B.easeOutBounce(2*a-1)+0.5}},q=s.canvas.width,u=s.canvas.height;window.devicePixelRatio&&(s.canvas.style.width=q+"px",s.canvas.style.height=u+"px",s.canvas.height=u*window.devicePixelRatio,s.canvas.width=q*window.devicePixelRatio,s.scale(window.devicePixelRatio,window.devicePixelRatio));this.PolarArea=function(a,c){r.PolarArea.defaults={scaleOverlay:!0,
-scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleShowLine:!0,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleFontFamily:"'Arial'",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animation:!0,animationSteps:100,animationEasing:"easeOutBounce",
-animateRotate:!0,animateScale:!1,onAnimationComplete:null};var b=c?y(r.PolarArea.defaults,c):r.PolarArea.defaults;return new G(a,b,s)};this.Radar=function(a,c){r.Radar.defaults={scaleOverlay:!1,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleShowLine:!0,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!1,scaleLabel:"<%=value%>",scaleFontFamily:"'Arial'",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",
-scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,angleShowLineOut:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:12,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,animation:!0,animationSteps:60,animationEasing:"easeOutQuart",onAnimationComplete:null};var b=c?y(r.Radar.defaults,c):r.Radar.defaults;return new H(a,b,s)};this.Pie=function(a,
-c){r.Pie.defaults={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animation:!0,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,onAnimationComplete:null};var b=c?y(r.Pie.defaults,c):r.Pie.defaults;return new I(a,b,s)};this.Doughnut=function(a,c){r.Doughnut.defaults={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animation:!0,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,
-onAnimationComplete:null};var b=c?y(r.Doughnut.defaults,c):r.Doughnut.defaults;return new J(a,b,s)};this.Line=function(a,c){r.Line.defaults={scaleOverlay:!1,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleFontFamily:"'Arial'",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,bezierCurve:!0,
-pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:2,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,animation:!0,animationSteps:60,animationEasing:"easeOutQuart",onAnimationComplete:null};var b=c?y(r.Line.defaults,c):r.Line.defaults;return new K(a,b,s)};this.Bar=function(a,c){r.Bar.defaults={scaleOverlay:!1,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleFontFamily:"'Arial'",
-scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,animation:!0,animationSteps:60,animationEasing:"easeOutQuart",onAnimationComplete:null};var b=c?y(r.Bar.defaults,c):r.Bar.defaults;return new L(a,b,s)};var G=function(a,c,b){var e,h,f,d,g,k,j,l,m;g=Math.min.apply(Math,[q,u])/2;g-=Math.max.apply(Math,[0.5*c.scaleFontSize,0.5*c.scaleLineWidth]);
-d=2*c.scaleFontSize;c.scaleShowLabelBackdrop&&(d+=2*c.scaleBackdropPaddingY,g-=1.5*c.scaleBackdropPaddingY);l=g;d=d?d:5;e=Number.MIN_VALUE;h=Number.MAX_VALUE;for(f=0;f<a.length;f++)a[f].value>e&&(e=a[f].value),a[f].value<h&&(h=a[f].value);f=Math.floor(l/(0.66*d));d=Math.floor(0.5*(l/d));m=c.scaleShowLabels?c.scaleLabel:null;c.scaleOverride?(j={steps:c.scaleSteps,stepValue:c.scaleStepWidth,graphMin:c.scaleStartValue,labels:[]},z(m,j.labels,j.steps,c.scaleStartValue,c.scaleStepWidth)):j=C(l,f,d,e,h,
-m);k=g/j.steps;x(c,function(){for(var a=0;a<j.steps;a++)if(c.scaleShowLine&&(b.beginPath(),b.arc(q/2,u/2,k*(a+1),0,2*Math.PI,!0),b.strokeStyle=c.scaleLineColor,b.lineWidth=c.scaleLineWidth,b.stroke()),c.scaleShowLabels){b.textAlign="center";b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;var e=j.labels[a];if(c.scaleShowLabelBackdrop){var d=b.measureText(e).width;b.fillStyle=c.scaleBackdropColor;b.beginPath();b.rect(Math.round(q/2-d/2-c.scaleBackdropPaddingX),Math.round(u/2-k*(a+
-1)-0.5*c.scaleFontSize-c.scaleBackdropPaddingY),Math.round(d+2*c.scaleBackdropPaddingX),Math.round(c.scaleFontSize+2*c.scaleBackdropPaddingY));b.fill()}b.textBaseline="middle";b.fillStyle=c.scaleFontColor;b.fillText(e,q/2,u/2-k*(a+1))}},function(e){var d=-Math.PI/2,g=2*Math.PI/a.length,f=1,h=1;c.animation&&(c.animateScale&&(f=e),c.animateRotate&&(h=e));for(e=0;e<a.length;e++)b.beginPath(),b.arc(q/2,u/2,f*v(a[e].value,j,k),d,d+h*g,!1),b.lineTo(q/2,u/2),b.closePath(),b.fillStyle=a[e].color,b.fill(),
-c.segmentShowStroke&&(b.strokeStyle=c.segmentStrokeColor,b.lineWidth=c.segmentStrokeWidth,b.stroke()),d+=h*g},b)},H=function(a,c,b){var e,h,f,d,g,k,j,l,m;a.labels||(a.labels=[]);g=Math.min.apply(Math,[q,u])/2;d=2*c.scaleFontSize;for(e=l=0;e<a.labels.length;e++)b.font=c.pointLabelFontStyle+" "+c.pointLabelFontSize+"px "+c.pointLabelFontFamily,h=b.measureText(a.labels[e]).width,h>l&&(l=h);g-=Math.max.apply(Math,[l,1.5*(c.pointLabelFontSize/2)]);g-=c.pointLabelFontSize;l=g=A(g,null,0);d=d?d:5;e=Number.MIN_VALUE;
-h=Number.MAX_VALUE;for(f=0;f<a.datasets.length;f++)for(m=0;m<a.datasets[f].data.length;m++)a.datasets[f].data[m]>e&&(e=a.datasets[f].data[m]),a.datasets[f].data[m]<h&&(h=a.datasets[f].data[m]);f=Math.floor(l/(0.66*d));d=Math.floor(0.5*(l/d));m=c.scaleShowLabels?c.scaleLabel:null;c.scaleOverride?(j={steps:c.scaleSteps,stepValue:c.scaleStepWidth,graphMin:c.scaleStartValue,labels:[]},z(m,j.labels,j.steps,c.scaleStartValue,c.scaleStepWidth)):j=C(l,f,d,e,h,m);k=g/j.steps;x(c,function(){var e=2*Math.PI/
-a.datasets[0].data.length;b.save();b.translate(q/2,u/2);if(c.angleShowLineOut){b.strokeStyle=c.angleLineColor;b.lineWidth=c.angleLineWidth;for(var d=0;d<a.datasets[0].data.length;d++)b.rotate(e),b.beginPath(),b.moveTo(0,0),b.lineTo(0,-g),b.stroke()}for(d=0;d<j.steps;d++){b.beginPath();if(c.scaleShowLine){b.strokeStyle=c.scaleLineColor;b.lineWidth=c.scaleLineWidth;b.moveTo(0,-k*(d+1));for(var f=0;f<a.datasets[0].data.length;f++)b.rotate(e),b.lineTo(0,-k*(d+1));b.closePath();b.stroke()}c.scaleShowLabels&&
-(b.textAlign="center",b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily,b.textBaseline="middle",c.scaleShowLabelBackdrop&&(f=b.measureText(j.labels[d]).width,b.fillStyle=c.scaleBackdropColor,b.beginPath(),b.rect(Math.round(-f/2-c.scaleBackdropPaddingX),Math.round(-k*(d+1)-0.5*c.scaleFontSize-c.scaleBackdropPaddingY),Math.round(f+2*c.scaleBackdropPaddingX),Math.round(c.scaleFontSize+2*c.scaleBackdropPaddingY)),b.fill()),b.fillStyle=c.scaleFontColor,b.fillText(j.labels[d],0,-k*(d+
-1)))}for(d=0;d<a.labels.length;d++){b.font=c.pointLabelFontStyle+" "+c.pointLabelFontSize+"px "+c.pointLabelFontFamily;b.fillStyle=c.pointLabelFontColor;var f=Math.sin(e*d)*(g+c.pointLabelFontSize),h=Math.cos(e*d)*(g+c.pointLabelFontSize);b.textAlign=e*d==Math.PI||0==e*d?"center":e*d>Math.PI?"right":"left";b.textBaseline="middle";b.fillText(a.labels[d],f,-h)}b.restore()},function(d){var e=2*Math.PI/a.datasets[0].data.length;b.save();b.translate(q/2,u/2);for(var g=0;g<a.datasets.length;g++){b.beginPath();
-b.moveTo(0,d*-1*v(a.datasets[g].data[0],j,k));for(var f=1;f<a.datasets[g].data.length;f++)b.rotate(e),b.lineTo(0,d*-1*v(a.datasets[g].data[f],j,k));b.closePath();b.fillStyle=a.datasets[g].fillColor;b.strokeStyle=a.datasets[g].strokeColor;b.lineWidth=c.datasetStrokeWidth;b.fill();b.stroke();if(c.pointDot){b.fillStyle=a.datasets[g].pointColor;b.strokeStyle=a.datasets[g].pointStrokeColor;b.lineWidth=c.pointDotStrokeWidth;for(f=0;f<a.datasets[g].data.length;f++)b.rotate(e),b.beginPath(),b.arc(0,d*-1*
-v(a.datasets[g].data[f],j,k),c.pointDotRadius,2*Math.PI,!1),b.fill(),b.stroke()}b.rotate(e)}b.restore()},b)},I=function(a,c,b){for(var e=0,h=Math.min.apply(Math,[u/2,q/2])-5,f=0;f<a.length;f++)e+=a[f].value;x(c,null,function(d){var g=-Math.PI/2,f=1,j=1;c.animation&&(c.animateScale&&(f=d),c.animateRotate&&(j=d));for(d=0;d<a.length;d++){var l=j*a[d].value/e*2*Math.PI;b.beginPath();b.arc(q/2,u/2,f*h,g,g+l);b.lineTo(q/2,u/2);b.closePath();b.fillStyle=a[d].color;b.fill();c.segmentShowStroke&&(b.lineWidth=
-c.segmentStrokeWidth,b.strokeStyle=c.segmentStrokeColor,b.stroke());g+=l}},b)},J=function(a,c,b){for(var e=0,h=Math.min.apply(Math,[u/2,q/2])-5,f=h*(c.percentageInnerCutout/100),d=0;d<a.length;d++)e+=a[d].value;x(c,null,function(d){var k=-Math.PI/2,j=1,l=1;c.animation&&(c.animateScale&&(j=d),c.animateRotate&&(l=d));for(d=0;d<a.length;d++){var m=l*a[d].value/e*2*Math.PI;b.beginPath();b.arc(q/2,u/2,j*h,k,k+m,!1);b.arc(q/2,u/2,j*f,k+m,k,!0);b.closePath();b.fillStyle=a[d].color;b.fill();c.segmentShowStroke&&
-(b.lineWidth=c.segmentStrokeWidth,b.strokeStyle=c.segmentStrokeColor,b.stroke());k+=m}},b)},K=function(a,c,b){var e,h,f,d,g,k,j,l,m,t,r,n,p,s=0;g=u;b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;t=1;for(d=0;d<a.labels.length;d++)e=b.measureText(a.labels[d]).width,t=e>t?e:t;q/a.labels.length<t?(s=45,q/a.labels.length<Math.cos(s)*t?(s=90,g-=t):g-=Math.sin(s)*t):g-=c.scaleFontSize;d=c.scaleFontSize;g=g-5-d;e=Number.MIN_VALUE;h=Number.MAX_VALUE;for(f=0;f<a.datasets.length;f++)for(l=
-0;l<a.datasets[f].data.length;l++)a.datasets[f].data[l]>e&&(e=a.datasets[f].data[l]),a.datasets[f].data[l]<h&&(h=a.datasets[f].data[l]);f=Math.floor(g/(0.66*d));d=Math.floor(0.5*(g/d));l=c.scaleShowLabels?c.scaleLabel:"";c.scaleOverride?(j={steps:c.scaleSteps,stepValue:c.scaleStepWidth,graphMin:c.scaleStartValue,labels:[]},z(l,j.labels,j.steps,c.scaleStartValue,c.scaleStepWidth)):j=C(g,f,d,e,h,l);k=Math.floor(g/j.steps);d=1;if(c.scaleShowLabels){b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;
-for(e=0;e<j.labels.length;e++)h=b.measureText(j.labels[e]).width,d=h>d?h:d;d+=10}r=q-d-t;m=Math.floor(r/(a.labels.length-1));n=q-t/2-r;p=g+c.scaleFontSize/2;x(c,function(){b.lineWidth=c.scaleLineWidth;b.strokeStyle=c.scaleLineColor;b.beginPath();b.moveTo(q-t/2+5,p);b.lineTo(q-t/2-r-5,p);b.stroke();0<s?(b.save(),b.textAlign="right"):b.textAlign="center";b.fillStyle=c.scaleFontColor;for(var d=0;d<a.labels.length;d++)b.save(),0<s?(b.translate(n+d*m,p+c.scaleFontSize),b.rotate(-(s*(Math.PI/180))),b.fillText(a.labels[d],
-0,0),b.restore()):b.fillText(a.labels[d],n+d*m,p+c.scaleFontSize+3),b.beginPath(),b.moveTo(n+d*m,p+3),c.scaleShowGridLines&&0<d?(b.lineWidth=c.scaleGridLineWidth,b.strokeStyle=c.scaleGridLineColor,b.lineTo(n+d*m,5)):b.lineTo(n+d*m,p+3),b.stroke();b.lineWidth=c.scaleLineWidth;b.strokeStyle=c.scaleLineColor;b.beginPath();b.moveTo(n,p+5);b.lineTo(n,5);b.stroke();b.textAlign="right";b.textBaseline="middle";for(d=0;d<j.steps;d++)b.beginPath(),b.moveTo(n-3,p-(d+1)*k),c.scaleShowGridLines?(b.lineWidth=c.scaleGridLineWidth,
-b.strokeStyle=c.scaleGridLineColor,b.lineTo(n+r+5,p-(d+1)*k)):b.lineTo(n-0.5,p-(d+1)*k),b.stroke(),c.scaleShowLabels&&b.fillText(j.labels[d],n-8,p-(d+1)*k)},function(d){function e(b,c){return p-d*v(a.datasets[b].data[c],j,k)}for(var f=0;f<a.datasets.length;f++){b.strokeStyle=a.datasets[f].strokeColor;b.lineWidth=c.datasetStrokeWidth;b.beginPath();b.moveTo(n,p-d*v(a.datasets[f].data[0],j,k));for(var g=1;g<a.datasets[f].data.length;g++)c.bezierCurve?b.bezierCurveTo(n+m*(g-0.5),e(f,g-1),n+m*(g-0.5),
-e(f,g),n+m*g,e(f,g)):b.lineTo(n+m*g,e(f,g));b.stroke();c.datasetFill?(b.lineTo(n+m*(a.datasets[f].data.length-1),p),b.lineTo(n,p),b.closePath(),b.fillStyle=a.datasets[f].fillColor,b.fill()):b.closePath();if(c.pointDot){b.fillStyle=a.datasets[f].pointColor;b.strokeStyle=a.datasets[f].pointStrokeColor;b.lineWidth=c.pointDotStrokeWidth;for(g=0;g<a.datasets[f].data.length;g++)b.beginPath(),b.arc(n+m*g,p-d*v(a.datasets[f].data[g],j,k),c.pointDotRadius,0,2*Math.PI,!0),b.fill(),b.stroke()}}},b)},L=function(a,
-c,b){var e,h,f,d,g,k,j,l,m,t,r,n,p,s,w=0;g=u;b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;t=1;for(d=0;d<a.labels.length;d++)e=b.measureText(a.labels[d]).width,t=e>t?e:t;q/a.labels.length<t?(w=45,q/a.labels.length<Math.cos(w)*t?(w=90,g-=t):g-=Math.sin(w)*t):g-=c.scaleFontSize;d=c.scaleFontSize;g=g-5-d;e=Number.MIN_VALUE;h=Number.MAX_VALUE;for(f=0;f<a.datasets.length;f++)for(l=0;l<a.datasets[f].data.length;l++)a.datasets[f].data[l]>e&&(e=a.datasets[f].data[l]),a.datasets[f].data[l]<
-h&&(h=a.datasets[f].data[l]);f=Math.floor(g/(0.66*d));d=Math.floor(0.5*(g/d));l=c.scaleShowLabels?c.scaleLabel:"";c.scaleOverride?(j={steps:c.scaleSteps,stepValue:c.scaleStepWidth,graphMin:c.scaleStartValue,labels:[]},z(l,j.labels,j.steps,c.scaleStartValue,c.scaleStepWidth)):j=C(g,f,d,e,h,l);k=Math.floor(g/j.steps);d=1;if(c.scaleShowLabels){b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;for(e=0;e<j.labels.length;e++)h=b.measureText(j.labels[e]).width,d=h>d?h:d;d+=10}r=q-d-t;m=
-Math.floor(r/a.labels.length);s=(m-2*c.scaleGridLineWidth-2*c.barValueSpacing-(c.barDatasetSpacing*a.datasets.length-1)-(c.barStrokeWidth/2*a.datasets.length-1))/a.datasets.length;n=q-t/2-r;p=g+c.scaleFontSize/2;x(c,function(){b.lineWidth=c.scaleLineWidth;b.strokeStyle=c.scaleLineColor;b.beginPath();b.moveTo(q-t/2+5,p);b.lineTo(q-t/2-r-5,p);b.stroke();0<w?(b.save(),b.textAlign="right"):b.textAlign="center";b.fillStyle=c.scaleFontColor;for(var d=0;d<a.labels.length;d++)b.save(),0<w?(b.translate(n+
-d*m,p+c.scaleFontSize),b.rotate(-(w*(Math.PI/180))),b.fillText(a.labels[d],0,0),b.restore()):b.fillText(a.labels[d],n+d*m+m/2,p+c.scaleFontSize+3),b.beginPath(),b.moveTo(n+(d+1)*m,p+3),b.lineWidth=c.scaleGridLineWidth,b.strokeStyle=c.scaleGridLineColor,b.lineTo(n+(d+1)*m,5),b.stroke();b.lineWidth=c.scaleLineWidth;b.strokeStyle=c.scaleLineColor;b.beginPath();b.moveTo(n,p+5);b.lineTo(n,5);b.stroke();b.textAlign="right";b.textBaseline="middle";for(d=0;d<j.steps;d++)b.beginPath(),b.moveTo(n-3,p-(d+1)*
-k),c.scaleShowGridLines?(b.lineWidth=c.scaleGridLineWidth,b.strokeStyle=c.scaleGridLineColor,b.lineTo(n+r+5,p-(d+1)*k)):b.lineTo(n-0.5,p-(d+1)*k),b.stroke(),c.scaleShowLabels&&b.fillText(j.labels[d],n-8,p-(d+1)*k)},function(d){b.lineWidth=c.barStrokeWidth;for(var e=0;e<a.datasets.length;e++){b.fillStyle=a.datasets[e].fillColor;b.strokeStyle=a.datasets[e].strokeColor;for(var f=0;f<a.datasets[e].data.length;f++){var g=n+c.barValueSpacing+m*f+s*e+c.barDatasetSpacing*e+c.barStrokeWidth*e;b.beginPath();
-b.moveTo(g,p);b.lineTo(g,p-d*v(a.datasets[e].data[f],j,k)+c.barStrokeWidth/2);b.lineTo(g+s,p-d*v(a.datasets[e].data[f],j,k)+c.barStrokeWidth/2);b.lineTo(g+s,p);c.barShowStroke&&b.stroke();b.closePath();b.fill()}}},b)},D=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)},F={}};
\ No newline at end of file
diff --git a/app/assets/javascripts/ci/projects.js.coffee b/app/assets/javascripts/ci/projects.js.coffee
index 7e028b4e115216e557728ca1928db877ef5f3f2e..e6406011d11438a454784b786f62a7c22d38a30f 100644
--- a/app/assets/javascripts/ci/projects.js.coffee
+++ b/app/assets/javascripts/ci/projects.js.coffee
@@ -1,6 +1,3 @@
 $(document).on 'click', '.badge-codes-toggle', ->
   $('.badge-codes-block').toggleClass("hide")
   return false
-
-$(document).on 'click', '.sync-now', ->
-  $(this).find('i').addClass('fa-spin')
diff --git a/app/assets/javascripts/line_highlighter.js.coffee b/app/assets/javascripts/line_highlighter.js.coffee
index e604e6025c2fb0caf51f826c08493126f3a2f268..2254a3f91aeb35dc08e06d43aea64a129d8598a2 100644
--- a/app/assets/javascripts/line_highlighter.js.coffee
+++ b/app/assets/javascripts/line_highlighter.js.coffee
@@ -6,7 +6,7 @@
 #
 # ### Example Markup
 #
-#   <div id="tree-content-holder">
+#   <div id="blob-content-holder">
 #     <div class="file-content">
 #       <div class="line-numbers">
 #         <a href="#L1" id="L1" data-line-number="1">1</a>
@@ -53,7 +53,7 @@ class @LineHighlighter
         $.scrollTo("#L#{range[0]}", offset: -150)
 
   bindEvents: ->
-    $('#tree-content-holder').on 'mousedown', 'a[data-line-number]', @clickHandler
+    $('#blob-content-holder').on 'mousedown', 'a[data-line-number]', @clickHandler
 
     # While it may seem odd to bind to the mousedown event and then throw away
     # the click event, there is a method to our madness.
@@ -62,7 +62,7 @@ class @LineHighlighter
     # active state even when the event is cancelled, resulting in an ugly border
     # around the link and/or a persisted underline text decoration.
 
-    $('#tree-content-holder').on 'click', 'a[data-line-number]', (event) ->
+    $('#blob-content-holder').on 'click', 'a[data-line-number]', (event) ->
       event.preventDefault()
 
   clickHandler: (event) =>
diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee
index 4e56791bde4c6aee02de91931e720adf1121a756..3e77ea515f819e36f3dca2fd0b641a25ab4cc267 100644
--- a/app/assets/javascripts/merge_request_tabs.js.coffee
+++ b/app/assets/javascripts/merge_request_tabs.js.coffee
@@ -69,7 +69,7 @@ class @MergeRequestTabs
   scrollToElement: (container) ->
     if window.location.hash
       top = $(container + " " + window.location.hash).offset().top
-      $('body').scrollTo(top);
+      $('body').scrollTo(top)
 
   # Activate a tab based on the current action
   activateTab: (action) ->
@@ -139,13 +139,16 @@ class @MergeRequestTabs
         @diffsLoaded = true
         @scrollToElement(".diffs")
 
-  toggleLoading: ->
-    $('.mr-loading-status .loading').toggle()
+  # Show or hide the loading spinner
+  #
+  # status - Boolean, true to show, false to hide
+  toggleLoading: (status) ->
+    $('.mr-loading-status .loading').toggle(status)
 
   _get: (options) ->
     defaults = {
-      beforeSend: @toggleLoading
-      complete: @toggleLoading
+      beforeSend: => @toggleLoading(true)
+      complete:   => @toggleLoading(false)
       dataType: 'json'
       type: 'GET'
     }
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index 4b9f0d6891228b4d22706a49ec8b8abc65d4cd32..ea75c656bccb5025a2b556913d6b66aefda73c32 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -63,12 +63,6 @@ class @Notes
     # fetch notes when tab becomes visible
     $(document).on "visibilitychange", @visibilityChange
 
-    # Chrome doesn't fire keypress or keyup for Command+Enter, so we need keydown.
-    $(document).on 'keydown', '.js-note-text', (e) ->
-      return if e.originalEvent.repeat
-      if e.keyCode == 10 || ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
-        $(@).closest('form').submit()
-
   cleanBinding: ->
     $(document).off "ajax:success", ".js-main-target-form"
     $(document).off "ajax:success", ".js-discussion-note-form"
@@ -82,7 +76,6 @@ class @Notes
     $(document).off "click", ".js-discussion-reply-button"
     $(document).off "click", ".js-add-diff-note-button"
     $(document).off "visibilitychange"
-    $(document).off "keydown", ".js-note-text"
     $(document).off "keyup", ".js-note-text"
     $(document).off "click", ".js-note-target-reopen"
     $(document).off "click", ".js-note-target-close"
diff --git a/app/assets/javascripts/tree.js.coffee b/app/assets/javascripts/tree.js.coffee
index d428db5b4227096ab1481fe345f6d4f764a49bb7..de8eebcd0b2c6c14a456bba0ceebadac817522b3 100644
--- a/app/assets/javascripts/tree.js.coffee
+++ b/app/assets/javascripts/tree.js.coffee
@@ -16,6 +16,9 @@ class @TreeView
     li = $("tr.tree-item")
     liSelected = null
     $('body').keydown (e) ->
+      if $("input:focus").length > 0 && (e.which == 38 || e.which == 40)
+        return false
+
       if e.which is 40
         if liSelected
           next = liSelected.next()
@@ -38,4 +41,4 @@ class @TreeView
         $(liSelected).focus()
       else if e.which is 13
         path = $('.tree-item.selected .tree-item-file-name a').attr('href')
-        Turbolinks.visit(path)
+        if path then Turbolinks.visit(path)
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index d9ede6379440525a0d6935209cb58a5841c6db56..7b060ce48532c36dadd52950c5f8f293a7515821 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -11,59 +11,41 @@
  *= require cal-heatmap
 */
 
+/*
+ * Welcome to GitLab css!
+ * If you need to add or modify UI component that is common for many pages
+ * like a table or typography then make changes in the framework/ directory.
+ * If you need to add unique style that should affect only one page - use pages/
+ * directory.
+ */
 
-@import "base/fonts";
-@import "base/variables";
-@import "base/mixins";
-@import "base/layout";
-
-
-/**
- * Customized Twitter bootstrap
+/*
+ * GitLab UI framework
  */
-@import 'base/gl_variables';
-@import 'base/gl_bootstrap';
+@import "framework";
 
-/**
+/*
  * NProgress load bar css
  */
 @import 'nprogress';
 @import 'nprogress-bootstrap';
 
-/**
+/*
  * Font icons
- *
  */
 @import "font-awesome";
 
-/**
- * UI themes:
- */
-@import "themes/**/*";
-
-/**
- * Generic css (forms, nav etc):
- */
-@import "generic/**/*";
-
-/**
+/*
  * Page specific styles (issues, projects etc):
  */
-
 @import "pages/**/*";
 
-/**
+/*
  * Code highlight
  */
 @import "highlight/**/*";
 
-/**
+/*
  * Styles for JS behaviors.
  */
-@import "behaviors.scss";
-
-/**
- * CI specific styles:
- */
-@import "ci/**/*";
-
+@import "behaviors.scss";
\ No newline at end of file
diff --git a/app/assets/stylesheets/base/variables.scss b/app/assets/stylesheets/base/variables.scss
deleted file mode 100644
index befd63832d572466c4ae3609ad8a9eeef7afe570..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/base/variables.scss
+++ /dev/null
@@ -1,46 +0,0 @@
-$hover: #FFFAF1;
-$gl-text-color: #54565B;
-$gl-text-green: #4A2;
-$gl-text-red: #D12F19;
-$gl-text-orange: #D90;
-$gl-header-color: #4c4e54;
-$gl-link-color: #333c48;
-$md-text-color: #444;
-$md-link-color: #3084bb;
-$nprogress-color: #c0392b;
-$gl-font-size: 15px;
-$list-font-size: 15px;
-$sidebar_collapsed_width: 62px;
-$sidebar_width: 230px;
-$avatar_radius: 50%;
-$code_font_size: 13px;
-$code_line_height: 1.5;
-$border-color: #dce0e6;
-$background-color: #F7F8FA;
-$header-height: 58px;
-$fixed-layout-width: 1200px;
-$gl-gray: #7f8fa4;
-$gl-padding: 16px;
-$gl-avatar-size: 46px;
-
-
-/*
- * State colors:
- */
-$gl-primary: #446e9b;
-$gl-success: #44c679;
-$gl-info: #00aaff;
-$gl-warning: #EB9532;
-$gl-danger: #d9534f;
-
-/*
- * Commit Diff Colors
- */
-$added: #63c363;
-$deleted: #f77;
-
-/*
- * Fonts
- */
-$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace;
-$regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif;
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
new file mode 100644
index 0000000000000000000000000000000000000000..1ec9d2fd84f1fe0e5c69104c7a33c7564f085458
--- /dev/null
+++ b/app/assets/stylesheets/framework.scss
@@ -0,0 +1,33 @@
+@import "framework/fonts";
+@import "framework/variables";
+@import "framework/mixins";
+@import "framework/layout";
+@import 'framework/tw_bootstrap_variables';
+@import 'framework/tw_bootstrap';
+
+@import "framework/avatar.scss";
+@import "framework/blocks.scss";
+@import "framework/buttons.scss";
+@import "framework/calendar.scss";
+@import "framework/callout.scss";
+@import "framework/common.scss";
+@import "framework/files.scss";
+@import "framework/filters.scss";
+@import "framework/flash.scss";
+@import "framework/forms.scss";
+@import "framework/gfm.scss";
+@import "framework/gitlab-theme.scss";
+@import "framework/header.scss";
+@import "framework/highlight.scss";
+@import "framework/issue_box.scss";
+@import "framework/jquery.scss";
+@import "framework/lists.scss";
+@import "framework/markdown_area.scss";
+@import "framework/mobile.scss";
+@import "framework/pagination.scss";
+@import "framework/selects.scss";
+@import "framework/sidebar.scss";
+@import "framework/tables.scss";
+@import "framework/timeline.scss";
+@import "framework/typography.scss";
+@import "framework/zen.scss";
diff --git a/app/assets/stylesheets/generic/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
similarity index 100%
rename from app/assets/stylesheets/generic/avatar.scss
rename to app/assets/stylesheets/framework/avatar.scss
diff --git a/app/assets/stylesheets/generic/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
similarity index 100%
rename from app/assets/stylesheets/generic/blocks.scss
rename to app/assets/stylesheets/framework/blocks.scss
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e5f0c0ad9eff29b73dd03d7bc005e03e760676db
--- /dev/null
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -0,0 +1,171 @@
+@mixin btn-default {
+  @include border-radius(2px);
+  border-width: 1px;
+  border-style: solid;
+  text-transform: uppercase;
+  font-size: 13px;
+  font-weight: 600;
+  line-height: 18px;
+  padding: 11px $gl-padding;
+  letter-spacing: .4px;
+
+  &:focus,
+  &:active {
+    outline: none;
+    @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
+  }
+}
+
+@mixin btn-middle {
+  @include btn-default;
+  @include border-radius(2px);
+  padding: 11px 24px;
+}
+
+@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
+  background-color: $light;
+  border-color: $border-light;
+  color: $color;
+
+  &:hover,
+  &:focus {
+    background-color: $normal;
+    border-color: $border-normal;
+    color: $color;
+  }
+
+  &:active {
+    @include box-shadow (inset 0 0 4px rgba(0, 0, 0, 0.12));
+
+    background-color: $dark;
+    border-color: $border-dark;
+    color: $color;
+  }
+}
+
+@mixin btn-green {
+  @include btn-color($green-light, $border-green-light, $green-normal, $border-green-normal, $green-dark, $border-green-dark, #FFFFFF);
+}
+
+@mixin btn-blue {
+  @include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF);
+}
+
+@mixin btn-orange {
+  @include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF);
+}
+
+@mixin btn-red {
+  @include btn-color($red-light, $border-red-light, $red-normal, $border-red-normal, $red-dark, $border-red-dark, #FFFFFF);
+}
+
+@mixin btn-gray {
+  @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, #313236);
+}
+
+@mixin btn-white {
+  @include btn-color($white-light, $border-white-light, $white-normal, $border-white-normal, $white-dark, $border-white-dark, #313236);
+}
+
+.btn {
+  @include btn-default;
+  @include btn-white;
+
+  &.btn-sm {
+    padding: 5px 10px;
+  }
+
+  &.btn-xs {
+    padding: 1px 5px;
+  }
+
+  &.btn-success,
+  &.btn-new,
+  &.btn-create,
+  &.btn-save,
+  &.btn-green {
+    @include btn-green;
+  }
+
+  &.btn-gray {
+    @include btn-gray;
+  }
+
+  &.btn-primary,
+  &.btn-info {
+    @include btn-blue;
+  }
+
+  &.btn-warning {
+    @include btn-orange;
+  }
+
+  &.btn-danger,
+  &.btn-remove,
+  &.btn-red {
+    @include btn-red;
+  }
+
+  &.btn-cancel {
+    float: right;
+  }
+
+  &.btn-close {
+    color: $gl-danger;
+    border-color: $gl-danger;
+    &:hover {
+      color: #B94A48;
+    }
+  }
+
+  &.btn-reopen {
+    color: $gl-success;
+    border-color: $gl-success;
+    &:hover {
+      color: #468847;
+    }
+  }
+
+  &.btn-grouped {
+    margin-right: 7px;
+    float: left;
+    &:last-child {
+      margin-right: 0px;
+    }
+  }
+}
+
+.btn-block {
+  width: 100%;
+  margin: 0;
+  margin-bottom: 15px;
+  &.btn {
+    padding: 6px 0;
+  }
+}
+
+.btn-group {
+  &.btn-grouped {
+    margin-right: 7px;
+    float: left;
+    &:last-child {
+      margin-right: 0px;
+    }
+  }
+}
+
+.btn-group-next {
+  .btn {
+    padding: 9px 0px;
+    font-size: 15px;
+    color: #7f8fa4;
+    border-color: #e7e9ed;
+    width: 140px;
+
+    &.active {
+      border-color: $gl-info;
+      background: $gl-info;
+      color: #fff;
+    }
+  }
+}
diff --git a/app/assets/stylesheets/generic/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
similarity index 100%
rename from app/assets/stylesheets/generic/calendar.scss
rename to app/assets/stylesheets/framework/calendar.scss
diff --git a/app/assets/stylesheets/generic/callout.scss b/app/assets/stylesheets/framework/callout.scss
similarity index 100%
rename from app/assets/stylesheets/generic/callout.scss
rename to app/assets/stylesheets/framework/callout.scss
diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/framework/common.scss
similarity index 98%
rename from app/assets/stylesheets/generic/common.scss
rename to app/assets/stylesheets/framework/common.scss
index 016cc015e9ce5db8568c361897b1606c68ccd34a..e1a1793be9c1564e787fd3c1c2bd0876d2cf6626 100644
--- a/app/assets/stylesheets/generic/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -381,6 +381,10 @@ table {
   &.no-bottom {
     margin-bottom: 0;
   }
+
+  &.no-top {
+    margin-top: 0;
+  }
 }
 
 .dropzone .dz-preview .dz-progress {
@@ -390,3 +394,7 @@ table {
 .dropzone .dz-preview .dz-progress .dz-upload {
   background: $gl-success !important;
 }
+
+.space-right {
+  margin-right: 10px;
+}
diff --git a/app/assets/stylesheets/generic/files.scss b/app/assets/stylesheets/framework/files.scss
similarity index 100%
rename from app/assets/stylesheets/generic/files.scss
rename to app/assets/stylesheets/framework/files.scss
diff --git a/app/assets/stylesheets/generic/filters.scss b/app/assets/stylesheets/framework/filters.scss
similarity index 100%
rename from app/assets/stylesheets/generic/filters.scss
rename to app/assets/stylesheets/framework/filters.scss
diff --git a/app/assets/stylesheets/generic/flash.scss b/app/assets/stylesheets/framework/flash.scss
similarity index 100%
rename from app/assets/stylesheets/generic/flash.scss
rename to app/assets/stylesheets/framework/flash.scss
diff --git a/app/assets/stylesheets/base/fonts.scss b/app/assets/stylesheets/framework/fonts.scss
similarity index 100%
rename from app/assets/stylesheets/base/fonts.scss
rename to app/assets/stylesheets/framework/fonts.scss
diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/framework/forms.scss
similarity index 86%
rename from app/assets/stylesheets/generic/forms.scss
rename to app/assets/stylesheets/framework/forms.scss
index 4282832e2bf66494d65f577cb588d7e527f09094..0edfe24f19584c8d340f4e79caa861b06901f726 100644
--- a/app/assets/stylesheets/generic/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -29,12 +29,6 @@ input[type='text'].danger {
   border-top: 1px solid $border-color;
 }
 
-@media (min-width: $screen-sm-min) {
-  .form-actions {
-    padding-left: 17%;
-  }
-}
-
 label {
   &.control-label {
     @extend .col-sm-2;
@@ -84,3 +78,17 @@ label {
 .wiki-content {
   margin-top: 35px;
 }
+
+.form-group .control-label {
+  font-weight: normal;
+}
+
+.form-control::-webkit-input-placeholder {
+  color: #7f8fa4;
+}
+
+.input-group {
+  .input-group-addon {
+    background-color: #f7f8fa;
+  }
+}
diff --git a/app/assets/stylesheets/generic/gfm.scss b/app/assets/stylesheets/framework/gfm.scss
similarity index 95%
rename from app/assets/stylesheets/generic/gfm.scss
rename to app/assets/stylesheets/framework/gfm.scss
index bd9200ace23a84ed73376793970d34d7a0e20d6e..5ae0520fd7b6d9eabe815bef2bfbc80be70b6227 100644
--- a/app/assets/stylesheets/generic/gfm.scss
+++ b/app/assets/stylesheets/framework/gfm.scss
@@ -22,4 +22,5 @@
 
 .gfm-commit, .gfm-commit_range {
   font-family: $monospace_font;
+  font-size: 90%;
 }
diff --git a/app/assets/stylesheets/themes/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss
similarity index 100%
rename from app/assets/stylesheets/themes/gitlab-theme.scss
rename to app/assets/stylesheets/framework/gitlab-theme.scss
diff --git a/app/assets/stylesheets/generic/header.scss b/app/assets/stylesheets/framework/header.scss
similarity index 96%
rename from app/assets/stylesheets/generic/header.scss
rename to app/assets/stylesheets/framework/header.scss
index 543ce41ab52e5b593d1776e3eee6505802b89f54..91e6975e2694eafd7a5a01a3a115199fd3184d1d 100644
--- a/app/assets/stylesheets/generic/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -50,15 +50,17 @@ header {
 
       .navbar-toggle {
         color: #666;
-        margin: 0;
+        margin: 6px 0;
         border-radius: 0;
         position: absolute;
         right: 2px;
-        top: 15px;
 
         &:hover {
           background-color: #EEE;
         }
+        &.active {
+          color: #7f8fa4;
+        }
       }
     }
   }
@@ -87,6 +89,7 @@ header {
 
     .navbar-collapse {
       float: right;
+      border-top: none;
     }
   }
 
diff --git a/app/assets/stylesheets/generic/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
similarity index 100%
rename from app/assets/stylesheets/generic/highlight.scss
rename to app/assets/stylesheets/framework/highlight.scss
diff --git a/app/assets/stylesheets/generic/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss
similarity index 94%
rename from app/assets/stylesheets/generic/issue_box.scss
rename to app/assets/stylesheets/framework/issue_box.scss
index b1fb87a683014f1990bfd9c0c2aee649133d16aa..93377e45e70a52aec9571670bb99b1233e9f978f 100644
--- a/app/assets/stylesheets/generic/issue_box.scss
+++ b/app/assets/stylesheets/framework/issue_box.scss
@@ -5,7 +5,7 @@
  */
 
 .issue-box {
-  @include border-radius(3px);
+  @include border-radius(2px);
 
   display: inline-block;
   padding: 10px $gl-padding;
diff --git a/app/assets/stylesheets/generic/jquery.scss b/app/assets/stylesheets/framework/jquery.scss
similarity index 100%
rename from app/assets/stylesheets/generic/jquery.scss
rename to app/assets/stylesheets/framework/jquery.scss
diff --git a/app/assets/stylesheets/base/layout.scss b/app/assets/stylesheets/framework/layout.scss
similarity index 88%
rename from app/assets/stylesheets/base/layout.scss
rename to app/assets/stylesheets/framework/layout.scss
index b91c15d8910f0b2fe2da7dca14863d9414685434..c7b3b60e76943a0fe77fde788b9b8529105cea3a 100644
--- a/app/assets/stylesheets/base/layout.scss
+++ b/app/assets/stylesheets/framework/layout.scss
@@ -5,6 +5,7 @@ html {
 
   body {
     padding-top: $header-height;
+    text-rendering: geometricPrecision;
   }
 }
 
diff --git a/app/assets/stylesheets/generic/lists.scss b/app/assets/stylesheets/framework/lists.scss
similarity index 95%
rename from app/assets/stylesheets/generic/lists.scss
rename to app/assets/stylesheets/framework/lists.scss
index 3bfed8de7720d9d0a0fa9de37d17c93a1d0863ba..c5764c36597a9a4276c4d83f9b06cd548a09b338 100644
--- a/app/assets/stylesheets/generic/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -117,8 +117,12 @@ ul.content-list {
     }
 
     .controls {
-      padding-top: 10px;
+      padding-top: 4px;
       float: right;
+
+      .btn {
+        padding: 10px 14px;
+      }
     }
   }
 }
diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
similarity index 100%
rename from app/assets/stylesheets/generic/markdown_area.scss
rename to app/assets/stylesheets/framework/markdown_area.scss
diff --git a/app/assets/stylesheets/base/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
similarity index 55%
rename from app/assets/stylesheets/base/mixins.scss
rename to app/assets/stylesheets/framework/mixins.scss
index c74a6d3982499eba5eeb79bb9d33add22e05ce76..089e6958eebef10cc353c4c208e4f718c27eb790 100644
--- a/app/assets/stylesheets/base/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -54,147 +54,6 @@
   @include box-shadow(0 0 0 3px #f1f1f1);
 }
 
-@mixin md-typography {
-  color: $md-text-color;
-
-  a {
-    color: $md-link-color;
-  }
-
-  img {
-    max-width: 100%;
-  }
-
-  *:first-child {
-    margin-top: 0;
-  }
-
-  code {
-    font-family: $monospace_font;
-    white-space: pre;
-    word-wrap: normal;
-    padding: 1px 2px;
-  }
-
-  kbd {
-    display: inline-block;
-    padding: 3px 5px;
-    font-size: 11px;
-    line-height: 10px;
-    color: #555;
-    vertical-align: middle;
-    background-color: #FCFCFC;
-    border-width: 1px;
-    border-style: solid;
-    border-color: #CCC #CCC #BBB;
-    border-image: none;
-    border-radius: 3px;
-    box-shadow: 0px -1px 0px #BBB inset;
-  }
-
-  h1 {
-    font-size: 1.3em;
-    font-weight: 600;
-    margin: 24px 0 12px 0;
-    padding: 0 0 10px 0;
-    border-bottom: 1px solid #e7e9ed;
-    color: #313236;
-  }
-
-  h2 {
-    font-size: 1.2em;
-    font-weight: 600;
-    margin: 24px 0 12px 0;
-    color: #313236;
-  }
-
-  h3 {
-    margin: 24px 0 12px 0;
-    font-size: 1.25em;
-  }
-
-  h4 {
-    margin: 24px 0 12px 0;
-    font-size: 1.1em;
-  }
-
-  h5 {
-    margin: 24px 0 12px 0;
-    font-size: 1em;
-  }
-
-  h6 {
-    margin: 24px 0 12px 0;
-    font-size: 0.90em;
-  }
-
-  blockquote {
-    padding: 8px 21px;
-    margin: 12px 0 12px;
-    border-left: 3px solid #e7e9ed;
-  }
-
-  blockquote p {
-    color: #7f8fa4 !important;
-    font-size: 15px;
-    line-height: 1.5;
-  }
-
-  p {
-    color:#5c5d5e;
-    margin:6px 0 0 0;
-  }
-
-  table {
-    @extend .table;
-    @extend .table-bordered;
-    margin: 12px 0 12px 0;
-    color: #5c5d5e;
-    th {
-      background: #f8fafc;
-    }
-  }
-
-  pre {
-    margin: 12px 0 12px 0 !important;
-    background-color: #f8fafc !important;
-    font-size: 13px !important;
-    color: #5b6169 !important;
-    line-height: 1.6em !important;
-    @include border-radius(2px);
-  }
-
-  p > code {
-    font-weight: inherit;
-  }
-
-
-  ul {
-    color: #5c5d5e;
-  }
-
-  li {
-    line-height: 1.6em;
-  }
-
-  a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] {
-    &:before {
-      margin-right: 4px;
-
-      font: normal normal normal 14px/1 FontAwesome;
-      font-size: inherit;
-      text-rendering: auto;
-      -webkit-font-smoothing: antialiased;
-      content: "\f0c6";
-    }
-
-    &:hover:before {
-      text-decoration: none;
-    }
-  }
-}
-
-
 @mixin str-truncated($max_width: 82%) {
   display: inline-block;
   overflow: hidden;
diff --git a/app/assets/stylesheets/generic/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
similarity index 91%
rename from app/assets/stylesheets/generic/mobile.scss
rename to app/assets/stylesheets/framework/mobile.scss
index 36ae126f8653e12a2b67e0f8de7c6dcd9079b4b4..cea47fba19226c8ba688f5f9882c44a7b7a29549 100644
--- a/app/assets/stylesheets/generic/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -23,7 +23,7 @@
     margin-right: 0;
   }
 
-  .issues-filters,
+  .issues-details-filters,
   .dash-projects-filters,
   .check-all-holder {
     display: none;
@@ -83,6 +83,7 @@
 
   .center-top-menu {
     height: 45px;
+    margin-bottom: 30px;
 
     li a {
       font-size: 14px;
@@ -90,9 +91,11 @@
     }
   }
 
-  .projects-search-form {
-    margin: 0 -5px !important;
+  .activity-filter-block {
+    display: none;
+  }
 
+  .projects-search-form {
     .btn {
       display: none;
     }
@@ -100,6 +103,11 @@
 }
 
 @media (max-width: $screen-sm-max) {
+  .page-with-sidebar .content-wrapper {
+    padding: 0;
+    padding-top: 1px;
+  }
+
   .issues-filters {
     .milestone-filter, .labels-filter {
       display: none;
diff --git a/app/assets/stylesheets/generic/pagination.scss b/app/assets/stylesheets/framework/pagination.scss
similarity index 100%
rename from app/assets/stylesheets/generic/pagination.scss
rename to app/assets/stylesheets/framework/pagination.scss
diff --git a/app/assets/stylesheets/generic/selects.scss b/app/assets/stylesheets/framework/selects.scss
similarity index 69%
rename from app/assets/stylesheets/generic/selects.scss
rename to app/assets/stylesheets/framework/selects.scss
index f0860de1c4964ff383d5cb35028c431d17e39c76..cba621635b6eacb1b20c9288457ba14d38aca3a8 100644
--- a/app/assets/stylesheets/generic/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -8,7 +8,7 @@
     font-size: $gl-font-size;
     line-height: 1.42857143;
 
-    @include border-radius(4px);
+    @include border-radius(2px);
 
     .select2-arrow {
       background: #FFF;
@@ -18,8 +18,39 @@
   }
 }
 
+.select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice{
+  color: #7f8fa4;
+  border: 1px solid #e7e9ed;
+}
+
+.select2-drop {
+  @include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px);
+  @include border-radius (0px);
+
+  padding: 16px;
+  border: none !important;
+}
+
+.select2-results .select2-result-label {
+  padding: 16px;
+}
+
+.select2-drop{
+  color: #7f8fa4;
+}
+
+.select2-highlighted {
+  background: #3084bb !important;
+}
+
+.select2-results li.select2-result-with-children > .select2-result-label {
+  font-weight: 600;
+  color: #313236;
+}
+
+
 .select2-container-multi .select2-choices {
-  @include border-radius(4px);
+  @include border-radius(2px);
   border-color: #CCC;
 }
 
@@ -63,7 +94,7 @@
 
 .ajax-users-dropdown, .ajax-project-users-dropdown {
   .select2-search {
-    padding-top: 4px;
+    padding-top: 2px;
   }
 }
 
@@ -97,9 +128,6 @@
   }
   .user-name {
   }
-  .user-username {
-    color: #999;
-  }
 }
 
 .namespace-result {
@@ -114,5 +142,5 @@
 }
 
 .ajax-users-dropdown {
-  min-width: 225px !important;
+  min-width: 250px !important;
 }
diff --git a/app/assets/stylesheets/generic/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
similarity index 100%
rename from app/assets/stylesheets/generic/sidebar.scss
rename to app/assets/stylesheets/framework/sidebar.scss
diff --git a/app/assets/stylesheets/generic/tables.scss b/app/assets/stylesheets/framework/tables.scss
similarity index 54%
rename from app/assets/stylesheets/generic/tables.scss
rename to app/assets/stylesheets/framework/tables.scss
index a66e45577de181764870e87bae2937d4b3dd6ccf..789b34020c18cc5729b9b1647e939ac0d692c474 100644
--- a/app/assets/stylesheets/generic/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -1,5 +1,21 @@
 table {
   &.table {
+    .dropdown-menu a {
+      text-decoration: none;
+    }
+
+    .success,
+    .warning,
+    .danger,
+    .info {
+      color: #fff;
+
+      a:not(.btn) {
+        text-decoration: underline;
+        color: #fff;
+      }
+    }
+
     tr {
       td, th {
         padding: 8px 10px;
@@ -12,7 +28,7 @@ table {
         border-bottom: 1px solid $border-color !important;
       }
       td {
-        border-color: #F1F1F1 !important;
+        border-color: $table-border-color !important;
         border-bottom: 1px solid;
       }
     }
diff --git a/app/assets/stylesheets/generic/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
similarity index 93%
rename from app/assets/stylesheets/generic/timeline.scss
rename to app/assets/stylesheets/framework/timeline.scss
index 74bbaabad3974a57a581ff7c1487a2b01bd46418..bf21d7fce76d54e0af9e03205c1d1bc25d70afc9 100644
--- a/app/assets/stylesheets/generic/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -10,8 +10,8 @@
     margin-left: -$gl-padding;
     margin-right: -$gl-padding;
     color: $gl-gray;
-    border-bottom: 1px solid #f1f2f4;
-    border-right: 1px solid #f1f2f4;
+    border-bottom: 1px solid #ECEEF1;
+    border-right: 1px solid #ECEEF1;
 
     &:last-child {
       border-bottom: none;
diff --git a/app/assets/stylesheets/base/gl_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss
similarity index 92%
rename from app/assets/stylesheets/base/gl_bootstrap.scss
rename to app/assets/stylesheets/framework/tw_bootstrap.scss
index eb8d23d6453cc477e8a13cbb8b4401816958920b..99d028d1228ee84bb88394051806b27943db204e 100644
--- a/app/assets/stylesheets/base/gl_bootstrap.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap.scss
@@ -32,8 +32,6 @@
 @import "bootstrap/pager";
 @import "bootstrap/labels";
 @import "bootstrap/badges";
-@import "bootstrap/jumbotron";
-@import "bootstrap/thumbnails";
 @import "bootstrap/alerts";
 @import "bootstrap/progress-bars";
 @import "bootstrap/list-group";
@@ -251,23 +249,3 @@
 .text-info:hover {
   color: $brand-info;
 }
-
-// Tables =====================================================================
-
-table.table {
-  .dropdown-menu a {
-    text-decoration: none;
-  }
-
-  .success,
-  .warning,
-  .danger,
-  .info {
-    color: #fff;
-
-    a:not(.btn) {
-      text-decoration: underline;
-      color: #fff;
-    }
-  }
-}
diff --git a/app/assets/stylesheets/base/gl_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
similarity index 97%
rename from app/assets/stylesheets/base/gl_variables.scss
rename to app/assets/stylesheets/framework/tw_bootstrap_variables.scss
index 7378d404008d04b9bc8fad66d255bfe0f071274e..63868a34e2a1aa4855e561f25540ae746683f8af 100644
--- a/app/assets/stylesheets/base/gl_variables.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
@@ -22,8 +22,8 @@ $brand-info:     $gl-info;
 $brand-warning:  $gl-warning;
 $brand-danger:   $gl-danger;
 
-$border-radius-base:        3px !default;
-$border-radius-large:       5px !default;
+$border-radius-base:        2px !default;
+$border-radius-large:       2px !default;
 $border-radius-small:       2px !default;
 
 
@@ -156,3 +156,5 @@ $nav-link-padding: 13px $gl-padding;
 $pre-bg:           #f8fafc !default;
 $pre-color:        $gl-gray !default;
 $pre-border-color: #e7e9ed;
+
+$table-bg-accent: $background-color;
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
new file mode 100644
index 0000000000000000000000000000000000000000..bf36f96cc97f225c8735e202cf2b3248ef5828c2
--- /dev/null
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -0,0 +1,271 @@
+@mixin md-typography {
+  color: $md-text-color;
+
+  a {
+    color: $md-link-color;
+  }
+
+  img {
+    max-width: 100%;
+  }
+
+  *:first-child {
+    margin-top: 0;
+  }
+
+  code {
+    font-family: $monospace_font;
+    white-space: pre;
+    word-wrap: normal;
+    padding: 1px 2px;
+  }
+
+  kbd {
+    display: inline-block;
+    padding: 3px 5px;
+    font-size: 11px;
+    line-height: 10px;
+    color: #555;
+    vertical-align: middle;
+    background-color: #FCFCFC;
+    border-width: 1px;
+    border-style: solid;
+    border-color: #CCC #CCC #BBB;
+    border-image: none;
+    border-radius: 3px;
+    box-shadow: 0px -1px 0px #BBB inset;
+  }
+
+  h1 {
+    font-size: 1.3em;
+    font-weight: 600;
+    margin: 24px 0 12px 0;
+    padding: 0 0 10px 0;
+    border-bottom: 1px solid #e7e9ed;
+    color: #313236;
+  }
+
+  h2 {
+    font-size: 1.2em;
+    font-weight: 600;
+    margin: 24px 0 12px 0;
+    color: #313236;
+  }
+
+  h3 {
+    margin: 24px 0 12px 0;
+    font-size: 1.25em;
+  }
+
+  h4 {
+    margin: 24px 0 12px 0;
+    font-size: 1.1em;
+  }
+
+  h5 {
+    margin: 24px 0 12px 0;
+    font-size: 1em;
+  }
+
+  h6 {
+    margin: 24px 0 12px 0;
+    font-size: 0.90em;
+  }
+
+  blockquote {
+    padding: 8px 21px;
+    margin: 12px 0 12px;
+    border-left: 3px solid #e7e9ed;
+  }
+
+  blockquote p {
+    color: #7f8fa4 !important;
+    font-size: 15px;
+    line-height: 1.5;
+  }
+
+  p {
+    color:#5c5d5e;
+    margin:6px 0 0 0;
+  }
+
+  table {
+    @extend .table;
+    @extend .table-bordered;
+    margin: 12px 0 12px 0;
+    color: #5c5d5e;
+    th {
+      background: #f8fafc;
+    }
+  }
+
+  pre {
+    margin: 12px 0 12px 0 !important;
+    background-color: #f8fafc !important;
+    font-size: 13px !important;
+    color: #5b6169 !important;
+    line-height: 1.6em !important;
+    @include border-radius(2px);
+  }
+
+  p > code {
+    font-weight: inherit;
+  }
+
+
+  ul {
+    color: #5c5d5e;
+  }
+
+  li {
+    line-height: 1.6em;
+  }
+
+  a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] {
+    &:before {
+      margin-right: 4px;
+
+      font: normal normal normal 14px/1 FontAwesome;
+      font-size: inherit;
+      text-rendering: auto;
+      -webkit-font-smoothing: antialiased;
+      content: "\f0c6";
+    }
+
+    &:hover:before {
+      text-decoration: none;
+    }
+  }
+}
+
+
+/**
+ * Headers
+ *
+ */
+body {
+  text-rendering:optimizeLegibility;
+  -webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px;
+}
+
+.page-title {
+  margin-top: 0px;
+  line-height: 1.3;
+  font-size: 1.25em;
+  font-weight: 600;
+}
+
+.page-title-empty {
+  margin-top: 0px;
+  line-height: 1.3;
+  font-size: 1.25em;
+  font-weight: 600;
+  margin: 12px 7px 12px 7px;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  color: $gl-header-color;
+  font-weight: 500;
+}
+
+/** CODE **/
+pre {
+  font-family: $monospace_font;
+
+  &.dark {
+    background: #333;
+    color: $background-color;
+  }
+
+  &.plain-readme {
+    background: none;
+    border: none;
+    padding: 0;
+    margin: 0;
+    font-size: 14px;
+  }
+}
+
+.monospace {
+  font-family: $monospace_font;
+}
+
+code {
+  &.key-fingerprint {
+    background: $body-bg;
+    color: $text-color;
+  }
+}
+
+a > code {
+  color: $link-color;
+}
+
+/**
+ * Wiki typography
+ *
+ */
+.wiki {
+  @include md-typography;
+
+  word-wrap: break-word;
+  padding: 7px;
+
+  /* Link to current header. */
+  h1, h2, h3, h4, h5, h6 {
+    position: relative;
+
+    a.anchor {
+      // Setting `display: none` would prevent the anchor being scrolled to, so
+      // instead we set the height to 0 and it gets updated on hover.
+      height: 0;
+    }
+
+    &:hover > a.anchor {
+      $size: 16px;
+      position: absolute;
+      right: 100%;
+      top: 50%;
+      margin-top: -$size/2;
+      margin-right: 0px;
+      padding-right: 20px;
+      display: inline-block;
+      width: $size;
+      height: $size;
+      background-image: image-url("icon-link.png");
+      background-size: contain;
+      background-repeat: no-repeat;
+    }
+  }
+
+  ul,ol {
+    padding: 0;
+    margin: 6px 0 6px 18px !important;
+  }
+  ol {
+    color: #5c5d5e;
+  }
+}
+
+.md-area {
+  @include md-typography;
+}
+
+.md {
+  @include md-typography;
+}
+
+/**
+ * Textareas intended for GFM
+ *
+ */
+textarea.js-gfm-input {
+  font-family: $monospace_font;
+}
+
+.md-preview {
+}
+
+.strikethrough {
+  text-decoration: line-through;
+}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
new file mode 100644
index 0000000000000000000000000000000000000000..91954683c3e8db28989abfd7fd970c2e35cd3a73
--- /dev/null
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -0,0 +1,99 @@
+$hover: #FFFAF1;
+$gl-text-color: #54565B;
+$gl-text-green: #4A2;
+$gl-text-red: #D12F19;
+$gl-text-orange: #D90;
+$gl-header-color: #4c4e54;
+$gl-link-color: #333c48;
+$md-text-color: #444;
+$md-link-color: #3084bb;
+$nprogress-color: #c0392b;
+$gl-font-size: 15px;
+$list-font-size: 15px;
+$sidebar_collapsed_width: 62px;
+$sidebar_width: 230px;
+$avatar_radius: 50%;
+$code_font_size: 13px;
+$code_line_height: 1.5;
+$border-color: #dce0e6;
+$table-border-color: #eef0f2;
+$background-color: #F7F8FA;
+$header-height: 58px;
+$fixed-layout-width: 1200px;
+$gl-gray: #7f8fa4;
+$gl-padding: 16px;
+$gl-avatar-size: 46px;
+
+/*
+ * Color schema
+ */
+
+$white-light: #FFFFFF;
+$white-normal: #DCE0E5;
+$white-dark: #E4E7ED;
+
+$gray-light: #F0F2F5;
+$gray-normal: #DCE0E5;
+$gray-dark: #E4E7ED;
+
+$green-light: #31AF64;
+$green-normal: #2FAA60;
+$green-dark: #2CA05B;
+
+$blue-light: #2EA8E5;
+$blue-normal: #2D9FD8;
+$blue-dark: #2897CE;
+
+$orange-light: #FC6443;
+$orange-normal: #E75E40;
+$orange-dark: #CE5237;
+
+$red-light: #F43263;
+$red-normal: #E52C5A;
+$red-dark: #D22852;
+
+$border-white-light: #E3E7EC;
+$border-white-normal: #D6DAE2;
+$border-white-dark: #C6CACF;
+
+$border-gray-light: #DCE0E5;
+$border-gray-normal: #D6DAE2;
+$border-gray-dark: #C6CACF;
+
+$border-green-light: #2FAA60;
+$border-green-normal: #2CA05B;
+$border-green-dark: #279654;
+
+$border-blue-light: #2D9FD8;
+$border-blue-normal: #2897CE;
+$border-blue-dark: #258DC1;
+
+$border-orange-light: #ED5C3D;
+$border-orange-normal: #CE5237;
+$border-orange-dark: #C14E35;
+
+$border-red-light: #E52C5A;
+$border-red-normal: #D22852;
+$border-red-dark: #CA264F;
+
+
+/*
+ * State colors:
+ */
+$gl-primary: $blue-normal;
+$gl-success: $green-normal;
+$gl-info: $blue-normal;
+$gl-warning: $orange-normal;
+$gl-danger: $red-normal;
+
+/*
+ * Commit Diff Colors
+ */
+$added: #63c363;
+$deleted: #f77;
+
+/*
+ * Fonts
+ */
+$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace;
+$regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif;
diff --git a/app/assets/stylesheets/generic/zen.scss b/app/assets/stylesheets/framework/zen.scss
similarity index 100%
rename from app/assets/stylesheets/generic/zen.scss
rename to app/assets/stylesheets/framework/zen.scss
diff --git a/app/assets/stylesheets/generic/buttons.scss b/app/assets/stylesheets/generic/buttons.scss
deleted file mode 100644
index cf76f538e01eaf9dcd143baee467137bfb1d4b2c..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/generic/buttons.scss
+++ /dev/null
@@ -1,228 +0,0 @@
-body {
-    text-rendering: geometricPrecision;
-}
-.btn {
-  @extend .btn-default;
-
-  &.btn-new {
-    @extend .btn-success;
-  }
-
-  &.btn-create {
-    @extend .btn-success;
-  }
-
-  &.btn-save {
-    @extend .btn-success;
-  }
-
-  &.btn-remove {
-    @extend .btn-danger;
-  }
-
-  &.btn-cancel {
-    float: right;
-  }
-
-  &.btn-close {
-    color: $gl-danger;
-    border-color: $gl-danger;
-    &:hover {
-      color: #B94A48;
-    }
-  }
-
-  &.btn-reopen {
-    color: $gl-success;
-    border-color: $gl-success;
-    &:hover {
-      color: #468847;
-    }
-  }
-
-  &.btn-grouped {
-    margin-right: 7px;
-    float: left;
-    &:last-child {
-      margin-right: 0px;
-    }
-  }
-
-  &.btn-save {
-    @extend .btn-primary;
-  }
-
-  &.btn-new, &.btn-create {
-    @extend .btn-success;
-  }
-}
-
-.btn-block {
-  width: 100%;
-  margin: 0;
-  margin-bottom: 15px;
-  &.btn {
-    padding: 6px 0;
-  }
-}
-
-.btn-group {
-  &.btn-grouped {
-    margin-right: 7px;
-    float: left;
-    &:last-child {
-      margin-right: 0px;
-    }
-  }
-}
-
-.btn-group-next {
-  .btn {
-    padding: 9px 0px;
-    font-size: 15px;
-    color: #7f8fa4;
-    border-color: #e7e9ed;
-    width: 140px;
-
-    &.active {
-      border-color: $gl-info;
-      background: $gl-info;
-      color: #fff;
-    }
-  }
-}
-
-@mixin btn-info {
-  @include border-radius(2px);
-  
-  border-width: 1px;
-  border-style: solid;
-  text-transform: uppercase;
-  font-size: 13px;
-  font-weight: 600;
-  line-height: 18px;
-  padding: 11px 16px;
-  letter-spacing: .4px;
-  
-  &:hover {
-    border-width: 1px;
-    border-style: solid;
-  }
-  
-  &:focus {
-    border-width: 1px;
-    border-style: solid;
-  }
-  
-  &:active {
-    @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
-    border-width: 1px;
-    border-style: solid;
-  }
-}
-
-@mixin btn-middle {
-  @include border-radius(2px);
-  
-  border-width: 1px;
-  border-style: solid;
-  text-transform: uppercase;
-  font-size: 13px;
-  font-weight: 600;
-  line-height: 18px;
-  padding: 11px 24px;
-  letter-spacing: .4px;
-  
-  &:hover {
-    border-width: 1px;
-    border-style: solid;
-  }
-  
-  &:focus {
-    border-width: 1px;
-    border-style: solid;
-  }
-  
-  &:active {
-    @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
-    border-width: 1px;
-    border-style: solid;
-    }
-}
-
-
-@mixin btn-green {
-  background-color: #28b061;
-  border: 1px solid #26a65c;
-  color: #fff;
-    
-     &:hover {
-       background-color: #26ab5d;
-       border: 1px solid #229954;
-       color: #fff;
-     }
-     
-     &:focus {
-       background-color: #26ab5d;
-       border: 1px solid #229954;
-       color: #fff;
-     }
-     
-     &:active {
-       @include box-shadow (inset 0 0 4px rgba(0, 0, 0, 0.12));
-        
-       background-color: #23a158 !important;
-       border: 1px solid #229954 !important;
-       color: #fff !important;
-     } 
-}
-
-/*Butons*/
-
-@mixin bnt-project {
-  background-color: #f0f2f5;
-  border-color: #dce0e5;
-  color: #313236;
-  
-  &:hover {
-    border-color:#dce0e5;
-    background-color: #ebeef2;
-    color: #313236;
-  }
-   
-  &:focus {
-    border-color: #dce0e5;
-    background-color: #ebeef2;
-    color: #313236;
-  }
-  
-  &:active {
-   @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
-   
-      color: #313236 !important;
-      border-color: #c6cacf !important;
-      background-color: #e4e7ed !important;
-  }
-}
-
-@mixin btn-remove {
-  background-color: #f72e60;
-  border-color: #ee295a;
-  
-  &:hover {
-    background-color: #e82757;
-    border-color: #e32555;
-  }
-  
-  &:focus {
-    background-color: #e82757;
-    border-color: #e32555;
-  }
-  
-  &:active {
-    @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
-    background-color: #d42450 !important;
-    border-color: #e12554 !important;
-  }
-  
-}
\ No newline at end of file
diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss
deleted file mode 100644
index 6a3cb49baaefc45125a369054aac6a8245d951b0..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/generic/typography.scss
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * Headers
- *
- */
-body {
-  text-rendering:optimizeLegibility;
-  -webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px;
-}
- 
-.page-title {
-  margin-top: 0px;
-  line-height: 1.3;
-  font-size: 1.25em;
-  font-weight: 600;
-}
-
-.page-title-empty {
-  margin-top: 0px;
-  line-height: 1.3;
-  font-size: 1.25em;
-  font-weight: 600;
-  margin: 12px 7px 12px 7px;
-}
-
-h1, h2, h3, h4, h5, h6 {
-  color: $gl-header-color;
-  font-weight: 500;
-}
-
-/** CODE **/
-pre {
-  font-family: $monospace_font;
-
-  &.dark {
-    background: #333;
-    color: $background-color;
-  }
-
-  &.plain-readme {
-    background: none;
-    border: none;
-    padding: 0;
-    margin: 0;
-    font-size: 14px;
-  }
-}
-
-.monospace {
-  font-family: $monospace_font;
-}
-
-code {
-  &.key-fingerprint {
-    background: $body-bg;
-    color: $text-color;
-  }
-}
-
-a > code {
-  color: $link-color;
-}
-
-/**
- * Wiki typography
- *
- */
-.wiki {
-  @include md-typography;
-
-  word-wrap: break-word;
-  padding: 7px;
-
-  /* Link to current header. */
-  h1, h2, h3, h4, h5, h6 {
-    position: relative;
-
-    a.anchor {
-      // Setting `display: none` would prevent the anchor being scrolled to, so
-      // instead we set the height to 0 and it gets updated on hover.
-      height: 0;
-    }
-
-    &:hover > a.anchor {
-      $size: 16px;
-      position: absolute;
-      right: 100%;
-      top: 50%;
-      margin-top: -$size/2;
-      margin-right: 0px;
-      padding-right: 20px;
-      display: inline-block;
-      width: $size;
-      height: $size;
-      background-image: image-url("icon-link.png");
-      background-size: contain;
-      background-repeat: no-repeat;
-    }
-  }
-
-  ul,ol {
-    padding: 0;
-    margin: 6px 0 6px 18px !important;
-  }
-  ol {
-    color: #5c5d5e;
-  }
-}
-
-.md-area {
-  @include md-typography;
-}
-
-.md {
-  @include md-typography;
-}
-
-/**
- * Textareas intended for GFM
- *
- */
-textarea.js-gfm-input {
-  font-family: $monospace_font;
-}
-
-.md-preview {
-}
-
-.strikethrough {
-  text-decoration: line-through;
-}
\ No newline at end of file
diff --git a/app/assets/stylesheets/ci/builds.scss b/app/assets/stylesheets/pages/builds.scss
similarity index 93%
rename from app/assets/stylesheets/ci/builds.scss
rename to app/assets/stylesheets/pages/builds.scss
index a11a935b54dab46e41c45e6a86cb960e6533adfd..74dc3e321c1c6e2cfdfffe0faf9c79b20971ebb6 100644
--- a/app/assets/stylesheets/ci/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -1,4 +1,4 @@
-.ci-body {
+.build-page {
   pre.trace {
     background: #111111;
     color: #fff;
@@ -67,4 +67,9 @@
       color: #3084bb !important;
     }
   }
+
+  .build-top-menu {
+    margin-top: 0;
+    margin-bottom: 2px;
+  }
 }
diff --git a/app/assets/stylesheets/ci/projects.scss b/app/assets/stylesheets/pages/ci_projects.scss
similarity index 100%
rename from app/assets/stylesheets/ci/projects.scss
rename to app/assets/stylesheets/pages/ci_projects.scss
diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss
index 741ff9051a26c5d99e8dca97f958d1893fa8f5a5..fbd7c363de108f414325d5714496668c9827259f 100644
--- a/app/assets/stylesheets/pages/commit.scss
+++ b/app/assets/stylesheets/pages/commit.scss
@@ -107,3 +107,16 @@
     z-index: 2;
   }
 }
+
+.commit-ci-menu {
+  padding: 0;
+  margin: 0;
+  list-style: none;
+  margin-top: 5px;
+  height: 56px;
+  margin: -16px;
+  padding: 16px;
+  text-align: center;
+  margin-top: 0px;
+  margin-bottom: 2px;
+}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index de2ae93df378b8ccfce5f5f24764bd10729dc874..4e121b95d13b14986749373eec8d66667eb3b998 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -1,5 +1,6 @@
 .commits-compare-switch{
-  @extend .btn;
+  @include btn-default;
+  @include btn-white;
   background: image-url("switch_icon.png") no-repeat center center;
   text-indent: -9999px;
   float: left;
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 5e7e59a6af82162ac5b999c33b1c884fe32ee220..d9ef06dc6b650ef7ea962a7ccac01f8a047aa664 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -1,3 +1,4 @@
+// Common
 .diff-file {
   margin-left: -$gl-padding;
   margin-right: -$gl-padding;
@@ -12,24 +13,17 @@
     color: #555;
     z-index: 10;
 
-    > span {
+    .diff-title {
       font-family: $monospace_font;
       word-break: break-all;
-      margin-right: 200px;
       display: block;
 
       .file-mode {
-        margin-left: 10px;
         color: #777;
       }
     }
 
-    .diff-btn-group {
-      float: right;
-      position: absolute;
-      top: 5px;
-      right: 15px;
-
+    .diff-controls {
       .btn {
         padding: 0px 10px;
         font-size: 13px;
@@ -90,12 +84,12 @@
       }
     }
 
-    tr.line_holder.parallel{
+    tr.line_holder.parallel {
       .old_line, .new_line, .diff_line {
         min-width: 50px;
       }
 
-      td.line_content.parallel{
+      td.line_content.parallel {
         width: 50%;
       }
     }
@@ -105,7 +99,7 @@
       padding: 0px;
       border: none;
       background: $background-color;
-      color: rgba(0,0,0,0.3);
+      color: rgba(0, 0, 0, 0.3);
       padding: 0px 5px;
       border-right: 1px solid $border-color;
       text-align: right;
@@ -117,7 +111,7 @@
         float: left;
         width: 35px;
         font-weight: normal;
-        color: rgba(0,0,0,0.3);
+        color: rgba(0, 0, 0, 0.3);
         &:hover {
           text-decoration: underline;
         }
@@ -168,7 +162,7 @@
     background: #ddd;
     text-align: center;
     padding: 30px;
-    .wrap{
+    .wrap {
       display: inline-block;
     }
 
@@ -176,7 +170,7 @@
       display: inline-block;
       background-color: #fff;
       line-height: 0;
-      img{
+      img {
         border: 1px solid #FFF;
         background: image-url('trans_bg.gif');
         max-width: 100%;
@@ -189,21 +183,21 @@
         border: 1px solid $added;
       }
     }
-    .image-info{
+    .image-info {
       font-size: 12px;
       margin: 5px 0 0 0;
       color: grey;
     }
 
-    .view.swipe{
+    .view.swipe {
       position: relative;
 
-      .swipe-frame{
+      .swipe-frame {
         display: block;
         margin: auto;
         position: relative;
       }
-      .swipe-wrap{
+      .swipe-wrap {
         overflow: hidden;
         border-left: 1px solid #999;
         position: absolute;
@@ -211,33 +205,33 @@
         top: 13px;
         right: 7px;
       }
-      .frame{
+      .frame {
         top: 0;
         right: 0;
         position: absolute;
-        &.deleted{
+        &.deleted {
           margin: 0;
           display: block;
           top: 13px;
           right: 7px;
         }
       }
-      .swipe-bar{
+      .swipe-bar {
         display: block;
         height: 100%;
         width: 15px;
         z-index: 100;
         position: absolute;
         cursor: pointer;
-        &:hover{
-          .top-handle{
+        &:hover {
+          .top-handle {
             background-position: -15px 3px;
           }
-          .bottom-handle{
+          .bottom-handle {
             background-position: -15px -11px;
           }
-        };
-        .top-handle{
+        }
+        .top-handle {
           display: block;
           height: 14px;
           width: 15px;
@@ -245,7 +239,7 @@
           top: 0px;
           background: image-url('swipemode_sprites.gif') 0 3px no-repeat;
         }
-        .bottom-handle{
+        .bottom-handle {
           display: block;
           height: 14px;
           width: 15px;
@@ -254,9 +248,10 @@
           background: image-url('swipemode_sprites.gif') 0 -11px no-repeat;
         }
       }
-    } //.view.swipe
-    .view.onion-skin{
-      .onion-skin-frame{
+    }
+    //.view.swipe
+    .view.onion-skin {
+      .onion-skin-frame {
         display: block;
         margin: auto;
         position: relative;
@@ -267,7 +262,7 @@
         top: 0px;
         left: 0px;
       }
-      .controls{
+      .controls {
         display: block;
         height: 14px;
         width: 300px;
@@ -277,7 +272,7 @@
         left: 50%;
         margin-left: -150px;
 
-        .drag-track{
+        .drag-track {
           display: block;
           position: absolute;
           left: 12px;
@@ -317,39 +312,40 @@
           background: image-url('onion_skin_sprites.gif') -2px -10px no-repeat;
         }
       }
-    } //.view.onion-skin
+    }
+    //.view.onion-skin
   }
-  .view-modes{
+  .view-modes {
     padding: 10px;
     text-align: center;
     background: #EEE;
 
-    ul, li{
+    ul, li {
       list-style: none;
       margin: 0;
       padding: 0;
       display: inline-block;
     }
 
-    li{
+    li {
       color: grey;
       border-left: 1px solid #c1c1c1;
       padding: 0 12px 0 16px;
       cursor: pointer;
-      &:first-child{
+      &:first-child {
         border-left: none;
       }
-      &:hover{
+      &:hover {
         text-decoration: underline;
       }
-      &.active{
-        &:hover{
+      &.active {
+        &:hover {
           text-decoration: none;
         }
         cursor: default;
         color: #333;
       }
-      &.disabled{
+      &.disabled {
         display: none;
       }
     }
@@ -373,3 +369,37 @@
   float: right;
   margin-top: -5px;
 }
+
+// Mobile
+@media (max-width: 480px) {
+  .diff-title {
+    margin: 0;
+
+    .file-mode {
+      display: none;
+    }
+  }
+
+  .diff-controls {
+    position: static;
+    text-align: center;
+  }
+}
+
+// Bigger screens
+@media (min-width: 481px) {
+  .diff-title {
+    margin-right: 200px;
+
+    .file-mode {
+      margin-left: 10px;
+    }
+  }
+
+  .diff-controls {
+    float: right;
+    position: absolute;
+    top: 5px;
+    right: 15px;
+  }
+}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index b5c61f7f91da6bed6e589992331739b41c2c6824..9da085a347337b7a7d7bf93232641049d4e2a606 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -54,21 +54,22 @@
     margin-top: -15px;
     padding: 10px 0;
     margin-bottom: 0;
-    color: $gl-gray;
+    color: #5c5d5e;
     font-size: 16px;
 
     .author {
-      color: $gl-gray;
+      color: #5c5d5e;
     }
 
     .issue-id {
-      font-size: 19px;
-      color: $gl-text-color;
+      color: #5c5d5e;
     }
   }
 
   .issue-title {
     margin: 0;
+    font-size: 23px;
+    color: #313236;
   }
 
   .description {
diff --git a/app/assets/stylesheets/ci/lint.scss b/app/assets/stylesheets/pages/lint.scss
similarity index 100%
rename from app/assets/stylesheets/ci/lint.scss
rename to app/assets/stylesheets/pages/lint.scss
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index d8c8e5ad0a4687fd510f08245bde00394d55f733..a1a5208c59c29c555660fc6465a29c6320a48b3d 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -3,12 +3,11 @@
  *
  */
 .mr-state-widget {
-  background: #f8fafc;
+  background: #F7F8FA;
   margin-bottom: 20px;
   color: $gl-gray;
-  border: 1px solid #eef0f2;
-  @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.05));
-  @include border-radius(3px);
+  border: 1px solid #dce0e6;
+  @include border-radius(2px);
 
   form {
     margin-bottom: 0;
@@ -77,10 +76,16 @@
     padding: 15px;
   }
 
+  .normal {
+    color: #5c5d5e;
+  }
+
   .mr-widget-body {
     h4 {
-      font-weight: bold;
+      font-weight: 600;
+      font-size: 17px;
       margin: 5px 0;
+      color: #313236;
     }
 
     p:last-child {
@@ -97,14 +102,26 @@
   }
 }
 
-.merge-request .merge-request-tabs{
+.merge-request .merge-request-tabs {
   @include nav-menu;
   margin: -$gl-padding;
   padding: $gl-padding;
   text-align: center;
-  border-top: 1px solid #e7e9ed;
-  margin-top: 18px;
-  margin-bottom: 3px;
+  margin-bottom: 1px;
+}
+
+// Mobile
+@media (max-width: 480px) {
+  .merge-request .merge-request-tabs {
+    margin: 0;
+    padding: 0;
+
+    li {
+      a {
+        padding: 0;
+      }
+    }
+  }
 }
 
 .mr_source_commit,
@@ -120,10 +137,12 @@
 }
 
 .label-branch {
-  color: #222;
+  color: #313236;
   font-family: $monospace_font;
   font-weight: bold;
   overflow: hidden;
+  font-size: 14px;
+  margin: 0 3px;
 }
 
 .mr-list {
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index fdc2c3332df913b35fcc2ad7c799b3cf99263279..4392f08942b6d939daecfe9ab670f8a955496adf 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -65,19 +65,18 @@
 
 .note-image-attach {
   @extend .col-md-4;
-  @extend .thumbnail;
   margin-left: 45px;
   float: none;
 }
 
 .common-note-form {
   margin: 0;
-  background: #f8fafc;
+  background: #F7F8FA;
   padding: $gl-padding;
   margin-left: -$gl-padding;
   margin-right: -$gl-padding;
-  border-right: 1px solid #f1f2f4;
-  border-top: 1px solid #f1f2f4;
+  border-right: 1px solid #ECEEF1;
+  border-top: 1px solid #ECEEF1;
   margin-bottom: -$gl-padding;
 }
 
@@ -168,7 +167,7 @@
 .comment-hints {
   color: #999;
   background: #FFF;
-  padding: 5px;
+  padding: 7px;
   margin-top: -11px;
   border: 1px solid $border-color;
   font-size: 13px;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 2a77f065aedce8566ada8b89d30f8614d10697ea..abb03b07f519484ee7afcee9e1173ea39ee808e1 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -18,7 +18,7 @@ ul.notes {
     font-size: 14px;
     padding-top: 10px;
     padding-bottom: 10px;
-    background: #f8fafc;
+    background: #FDFDFD;
 
     .timeline-icon {
       .avatar {
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 818aa10aefefb2115db5ad188b5842bc9b2ca2fc..f7a2284900398d3767ddf1814621f7e76f8a3fa5 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -13,11 +13,15 @@
 .edit_project {
   fieldset.features {
     .control-label {
-      font-weight: bold;
+      font-weight: normal;
     }
   }
 }
 
+.project-edit-content {
+  padding: 7px;
+}
+
 .project-name-holder {
   .help-inline {
     vertical-align: top;
@@ -59,6 +63,7 @@
     }
 
     p {
+      padding: 0 $gl-padding;
       color: #5c5d5e;
     }
   }
@@ -92,8 +97,7 @@
     margin-bottom: 0px;
 
     .btn {
-      @include bnt-project;
-      @include btn-info;
+      @include btn-gray;
 
       .count {
         display: inline-block;
@@ -149,7 +153,7 @@
 
 .input-group-btn {
   .btn {
-    @include bnt-project;
+    @include btn-gray;
     @include btn-middle;
 
     &:hover {
@@ -183,8 +187,8 @@
   margin: 0 12px 0 12px;
 
   .btn{
-    @include bnt-project;
-    @include btn-info;
+    @include btn-gray;
+    @include btn-default;
   }
 
   .dropdown-toggle  {
@@ -251,18 +255,19 @@
     margin-bottom: 10px;
 
     i {
-      margin: 0 3px;
+      margin: 2px 0;
       font-size: 20px;
     }
 
     .option-title {
-      font-weight: bold;
+      font-weight: normal;
       display: inline-block;
+      color: #313236;
     }
 
     .option-descr {
-      margin-left: 36px;
-      color: $gray;
+      margin-left: 29px;
+      color: #54565b;
     }
   }
 }
@@ -376,8 +381,8 @@ table.table.protected-branches-list tr.no-border {
   }
 
   .nav > li > a {
-    @include btn-info;
-    @include bnt-project;
+    @include btn-default;
+    @include btn-gray;
 
     background-color: transparent;
     border: 1px solid #f7f8fa;
@@ -437,7 +442,7 @@ pre.light-well {
 
   .btn-remove {
     @include btn-middle;
-    @include btn-remove;
+    @include btn-red;
 
     float: left !important;
   }
@@ -506,8 +511,3 @@ pre.light-well {
     margin-top: -1px;
   }
 }
-
-.inline-form {
-  display: inline-block;
-}
-
diff --git a/app/assets/stylesheets/ci/runners.scss b/app/assets/stylesheets/pages/runners.scss
similarity index 100%
rename from app/assets/stylesheets/ci/runners.scss
rename to app/assets/stylesheets/pages/runners.scss
diff --git a/app/assets/stylesheets/ci/status.scss b/app/assets/stylesheets/pages/status.scss
similarity index 100%
rename from app/assets/stylesheets/ci/status.scss
rename to app/assets/stylesheets/pages/status.scss
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 271cc547e2b31faa7c101b4b5c9242d29d9bc529..dadd86e88ccde1e062b438467d573f6c70044f95 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -1,7 +1,7 @@
 .tree-holder {
-  .tree-content-holder {
-    float: left;
-    width: 100%;
+  .tree-table-holder {
+    margin-left: -$gl-padding;
+    margin-right: -$gl-padding;
   }
 
   .tree_progress {
@@ -13,10 +13,15 @@
   }
 
   .tree-table {
-    @extend .table;
-    @include border-radius(0);
+    margin-bottom: 0;
 
     tr {
+      > td, > th {
+        padding: 10px $gl-padding;
+        line-height: 32px;
+        border-color: $table-border-color !important;
+      }
+
       &:hover {
         td {
           background: $hover;
@@ -27,9 +32,9 @@
       }
       &.selected {
         td {
-          background: $background-color;
-          border-top: 1px solid #EEE;
-          border-bottom: 1px solid #EEE;
+          background: $gray-dark;
+          border-top: 1px solid $border-gray-dark;
+          border-bottom: 1px solid $border-gray-dark;
         }
       }
     }
@@ -85,19 +90,6 @@
   margin-right: 15px;
 }
 
-.readme-holder {
-  margin: 0 auto;
-
-  .readme-file-title {
-    font-size: 14px;
-    font-weight: bold;
-    margin-bottom: 20px;
-    color: #777;
-    border-bottom: 1px solid #DDD;
-    padding: 10px 0;
-  }
-}
-
 .blob-commit-info {
   list-style: none;
   margin: 0;
diff --git a/app/assets/stylesheets/ci/xterm.scss b/app/assets/stylesheets/pages/xterm.scss
similarity index 99%
rename from app/assets/stylesheets/ci/xterm.scss
rename to app/assets/stylesheets/pages/xterm.scss
index 532dede0b2345cbe1a67bf7d0e1d956f541b5113..9a50096c0d07563086ca7ffa83bf997fd790ffbe 100644
--- a/app/assets/stylesheets/ci/xterm.scss
+++ b/app/assets/stylesheets/pages/xterm.scss
@@ -1,4 +1,4 @@
-.ci-body {
+.build-page {
   // color codes are based on http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg
   // see also: https://gist.github.com/jasonm23/2868981
 
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index be217e121b0d50408f90e69a946e23da05084b45..f0124c6bd603e23f8f89a75ae6f01b201b5816ea 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -30,7 +30,7 @@ class ApplicationController < ActionController::Base
 
   rescue_from ActiveRecord::RecordNotFound do |exception|
     log_exception(exception)
-    render "errors/not_found", layout: "errors", status: 404
+    render_404
   end
 
   protected
@@ -149,10 +149,6 @@ class ApplicationController < ActionController::Base
     render "errors/access_denied", layout: "errors", status: 404
   end
 
-  def not_found!
-    render "errors/not_found", layout: "errors", status: 404
-  end
-
   def git_not_found!
     render html: "errors/git_not_found", layout: "errors", status: 404
   end
diff --git a/app/controllers/ci/admin/runners_controller.rb b/app/controllers/ci/admin/runners_controller.rb
index 9a68add9083a46587ee0f51fbb2dfb7d4c64be4f..110954a612d04cfee9bab683345fb1e772b47596 100644
--- a/app/controllers/ci/admin/runners_controller.rb
+++ b/app/controllers/ci/admin/runners_controller.rb
@@ -6,7 +6,7 @@ module Ci
       @runners = Ci::Runner.order('id DESC')
       @runners = @runners.search(params[:search]) if params[:search].present?
       @runners = @runners.page(params[:page]).per(30)
-      @active_runners_cnt = Ci::Runner.where("contacted_at > ?", 1.minutes.ago).count
+      @active_runners_cnt = Ci::Runner.online.count
     end
 
     def show
@@ -66,7 +66,7 @@ module Ci
     end
 
     def runner_params
-      params.require(:runner).permit(:token, :description, :tag_list, :contacted_at, :active)
+      params.require(:runner).permit(:token, :description, :tag_list, :active)
     end
   end
 end
diff --git a/app/controllers/ci/builds_controller.rb b/app/controllers/ci/builds_controller.rb
deleted file mode 100644
index bf87f81439a24b4d121d82fb737550e43159c0d8..0000000000000000000000000000000000000000
--- a/app/controllers/ci/builds_controller.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-module Ci
-  class BuildsController < Ci::ApplicationController
-    before_action :authenticate_user!, except: [:status, :show]
-    before_action :authenticate_public_page!, only: :show
-    before_action :project
-    before_action :authorize_access_project!, except: [:status, :show]
-    before_action :authorize_manage_project!, except: [:status, :show, :retry, :cancel]
-    before_action :authorize_manage_builds!, only: [:retry, :cancel]
-    before_action :build, except: [:show]
-    layout 'ci/build'
-
-    def show
-      if params[:id] =~ /\A\d+\Z/
-        @build = build
-      else
-        # try to find commit by sha
-        commit = commit_by_sha
-
-        if commit
-          # Redirect to commit page
-          redirect_to ci_project_commit_path(@project, @build.commit)
-          return
-        end
-      end
-
-      raise ActiveRecord::RecordNotFound unless @build
-
-      @builds = @project.commits.find_by_sha(@build.sha).builds.order('id DESC')
-      @builds = @builds.where("id not in (?)", @build.id).page(params[:page]).per(20)
-      @commit = @build.commit
-
-      respond_to do |format|
-        format.html
-        format.json do
-          render json: @build.to_json(methods: :trace_html)
-        end
-      end
-    end
-
-    def retry
-      if @build.commands.blank?
-        return page_404
-      end
-
-      build = Ci::Build.retry(@build)
-
-      if params[:return_to]
-        redirect_to URI.parse(params[:return_to]).path
-      else
-        redirect_to ci_project_build_path(project, build)
-      end
-    end
-
-    def status
-      render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
-    end
-
-    def cancel
-      @build.cancel
-
-      redirect_to ci_project_build_path(@project, @build)
-    end
-
-    protected
-
-    def project
-      @project = Ci::Project.find(params[:project_id])
-    end
-
-    def build
-      @build ||= project.builds.unscoped.find_by(id: params[:id])
-    end
-
-    def commit_by_sha
-      @project.commits.find_by(sha: params[:id])
-    end
-  end
-end
diff --git a/app/controllers/ci/commits_controller.rb b/app/controllers/ci/commits_controller.rb
deleted file mode 100644
index 887e92f84cfa3c5ce884a235a579c988f1a4bb08..0000000000000000000000000000000000000000
--- a/app/controllers/ci/commits_controller.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-module Ci
-  class CommitsController < Ci::ApplicationController
-    before_action :authenticate_user!, except: [:status, :show]
-    before_action :authenticate_public_page!, only: :show
-    before_action :project
-    before_action :authorize_access_project!, except: [:status, :show, :cancel]
-    before_action :authorize_manage_builds!, only: [:cancel]
-    before_action :commit, only: :show
-    layout 'ci/commit'
-
-    def show
-      @builds = @commit.builds
-    end
-
-    def status
-      commit = Ci::Project.find(params[:project_id]).commits.find_by_sha!(params[:id])
-      render json: commit.to_json(only: [:id, :sha], methods: [:status, :coverage])
-    rescue ActiveRecord::RecordNotFound
-      render json: { status: "not_found" }
-    end
-
-    def cancel
-      commit.builds.running_or_pending.each(&:cancel)
-
-      redirect_to ci_project_commits_path(project, commit.sha)
-    end
-
-    private
-
-    def project
-      @project ||= Ci::Project.find(params[:project_id])
-    end
-
-    def commit
-      @commit ||= Ci::Project.find(params[:project_id]).commits.find_by_sha!(params[:id])
-    end
-  end
-end
diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb
index 33b8ae64659937f16aa42780d237c0d12a0bcf8d..7777aa180316f0f806b07be1612cbbeabcffb699 100644
--- a/app/controllers/ci/projects_controller.rb
+++ b/app/controllers/ci/projects_controller.rb
@@ -1,24 +1,11 @@
 module Ci
   class ProjectsController < Ci::ApplicationController
-    before_action :authenticate_user!, except: [:build, :badge, :show]
-    before_action :authenticate_public_page!, only: :show
-    before_action :project, only: [:build, :show, :badge, :toggle_shared_runners, :dumped_yaml]
-    before_action :authorize_access_project!, except: [:build, :badge, :show, :new]
+    before_action :project
+    before_action :authenticate_user!, except: [:build, :badge]
+    before_action :authorize_access_project!, except: [:badge]
     before_action :authorize_manage_project!, only: [:toggle_shared_runners, :dumped_yaml]
-    before_action :authenticate_token!, only: [:build]
     before_action :no_cache, only: [:badge]
-    protect_from_forgery except: :build
-
-    layout 'ci/project', except: [:index]
-
-    def show
-      @ref = params[:ref]
-
-      @commits = @project.commits.reverse_order
-      # TODO: this is broken
-      # @commits = @commits.where(ref: @ref) if @ref
-      @commits = @commits.page(params[:page]).per(20)
-    end
+    protect_from_forgery
 
     # Project status badge
     # Image with build status for sha or ref
diff --git a/app/controllers/ci/services_controller.rb b/app/controllers/ci/services_controller.rb
deleted file mode 100644
index 52c96a34ce88499ff1b2897dfcd561b9f96992fa..0000000000000000000000000000000000000000
--- a/app/controllers/ci/services_controller.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-module Ci
-  class ServicesController < Ci::ApplicationController
-    before_action :authenticate_user!
-    before_action :project
-    before_action :authorize_access_project!
-    before_action :authorize_manage_project!
-    before_action :service, only: [:edit, :update, :test]
-
-    respond_to :html
-
-    layout 'ci/project'
-
-    def index
-      @project.build_missing_services
-      @services = @project.services.reload
-    end
-
-    def edit
-    end
-
-    def update
-      if @service.update_attributes(service_params)
-        redirect_to edit_ci_project_service_path(@project, @service.to_param)
-      else
-        render 'edit'
-      end
-    end
-
-    def test
-      last_build = @project.builds.last
-
-      if @service.execute(last_build)
-        message = { notice: 'We successfully tested the service' }
-      else
-        message = { alert: 'We tried to test the service but error occurred' }
-      end
-
-      redirect_to :back, message
-    end
-
-    private
-
-    def project
-      @project = Ci::Project.find(params[:project_id])
-    end
-
-    def service
-      @service ||= @project.services.find { |service| service.to_param == params[:id] }
-    end
-
-    def service_params
-      params.require(:service).permit(
-        :type, :active, :webhook, :notify_only_broken_builds,
-        :email_recipients, :email_only_broken_builds, :email_add_pusher,
-        :hipchat_token, :hipchat_room, :hipchat_server
-      )
-    end
-  end
-end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 524218290c6635323bd2e038803cd2501560aafa..40fb15a5b3682b50fc00e96c9e3766f54869889f 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -88,7 +88,7 @@ class GroupsController < Groups::ApplicationController
   def destroy
     DestroyGroupService.new(@group, current_user).execute
 
-    redirect_to root_path, alert: "Group '#{@group.name} was deleted."
+    redirect_to root_path, alert: "Group '#{@group.name}' was successfully deleted."
   end
 
   protected
diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
index f84f85a7df842a522d7131b88cd269054cf78518..25e587248606ccde522f0b0f86fe2c4d35875107 100644
--- a/app/controllers/import/bitbucket_controller.rb
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -62,7 +62,7 @@ class Import::BitbucketController < Import::BaseController
   end
 
   def verify_bitbucket_import_enabled
-    not_found! unless bitbucket_import_enabled?
+    render_404 unless bitbucket_import_enabled?
   end
 
   def bitbucket_auth
diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb
index 849646cd6652403006d9a601a2909d03e70b474f..18300390851edcc3d2177ecd253951466b6e159b 100644
--- a/app/controllers/import/fogbugz_controller.rb
+++ b/app/controllers/import/fogbugz_controller.rb
@@ -99,6 +99,6 @@ class Import::FogbugzController < Import::BaseController
   end
 
   def verify_fogbugz_import_enabled
-    not_found! unless fogbugz_import_enabled?
+    render_404 unless fogbugz_import_enabled?
   end
 end
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index f21fbd9eccac0f02b41fbf40530d5c7364b68ff8..aae77d384c6ae745e5851cc49fb8de2bceea3e55 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -47,7 +47,7 @@ class Import::GithubController < Import::BaseController
   end
 
   def verify_github_import_enabled
-    not_found! unless github_import_enabled?
+    render_404 unless github_import_enabled?
   end
 
   def github_auth
diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb
index 27af19f5f616f89f19580fd03f95f6bd49faa573..23a396e8084f3dd2b32646f35b1d13f22a2bf0b3 100644
--- a/app/controllers/import/gitlab_controller.rb
+++ b/app/controllers/import/gitlab_controller.rb
@@ -44,7 +44,7 @@ class Import::GitlabController < Import::BaseController
   end
 
   def verify_gitlab_import_enabled
-    not_found! unless gitlab_import_enabled?
+    render_404 unless gitlab_import_enabled?
   end
 
   def gitlab_auth
diff --git a/app/controllers/import/gitorious_controller.rb b/app/controllers/import/gitorious_controller.rb
index f24cdb3709a0246eac25ef0c3807d6ebf9b170a2..eecbe380c9e7f7da752020f67833519bfb7c7f71 100644
--- a/app/controllers/import/gitorious_controller.rb
+++ b/app/controllers/import/gitorious_controller.rb
@@ -42,7 +42,7 @@ class Import::GitoriousController < Import::BaseController
   end
 
   def verify_gitorious_import_enabled
-    not_found! unless gitorious_import_enabled?
+    render_404 unless gitorious_import_enabled?
   end
 
 end
diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb
index 82fadeb7e832deba7f88860e3db3dd9a0e9cb9b4..41472a6fe6c16ba8dabb83751fc00ff05e521ac9 100644
--- a/app/controllers/import/google_code_controller.rb
+++ b/app/controllers/import/google_code_controller.rb
@@ -106,7 +106,7 @@ class Import::GoogleCodeController < Import::BaseController
   end
 
   def verify_google_code_import_enabled
-    not_found! unless google_code_import_enabled?
+    render_404 unless google_code_import_enabled?
   end
 
   def user_map
diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb
index 9c3763d5934e0245cc7e8133b2e136fdd7510fa1..548f1b9ebfec092ac360e8a7860a20b311cae950 100644
--- a/app/controllers/projects/avatars_controller.rb
+++ b/app/controllers/projects/avatars_controller.rb
@@ -12,7 +12,7 @@ class Projects::AvatarsController < Projects::ApplicationController
         filename: @blob.name
       )
     else
-      not_found!
+      render_404
     end
   end
 
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 8776721d243d7283b26b26728b23c7dd4e78077f..8cc2f21d8871ca974a4e8dce3e73b6d6cd67b920 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -8,7 +8,7 @@ class Projects::BlobController < Projects::ApplicationController
 
   before_action :require_non_empty_project, except: [:new, :create]
   before_action :authorize_download_code!
-  before_action :authorize_push_code!, only: [:destroy]
+  before_action :authorize_push_code!, only: [:destroy, :create]
   before_action :assign_blob_vars
   before_action :commit, except: [:new, :create]
   before_action :blob, except: [:new, :create]
@@ -25,7 +25,7 @@ class Projects::BlobController < Projects::ApplicationController
     result = Files::CreateService.new(@project, current_user, @commit_params).execute
 
     if result[:status] == :success
-      flash[:notice] = "Your changes have been successfully committed"
+      flash[:notice] = "The changes have been successfully committed"
       respond_to do |format|
         format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) }
         format.json { render json: { message: "success", filePath: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) } }
@@ -34,7 +34,7 @@ class Projects::BlobController < Projects::ApplicationController
       flash[:alert] = result[:message]
       respond_to do |format|
         format.html { render :new }
-        format.json { render json: { message: "failed", filePath: namespace_project_new_blob_path(@project.namespace, @project, @id) } }
+        format.json { render json: { message: "failed", filePath: namespace_project_blob_path(@project.namespace, @project, @id) } }
       end
     end
   end
@@ -113,14 +113,14 @@ class Projects::BlobController < Projects::ApplicationController
         end
       end
 
-      return not_found!
+      return render_404
     end
   end
 
   def commit
     @commit = @repository.commit(@ref)
 
-    return not_found! unless @commit
+    return render_404 unless @commit
   end
 
   def assign_blob_vars
@@ -128,7 +128,7 @@ class Projects::BlobController < Projects::ApplicationController
     @ref, @path = extract_ref(@id)
 
   rescue InvalidPathError
-    not_found!
+    render_404
   end
 
   def after_edit_path
@@ -154,7 +154,7 @@ class Projects::BlobController < Projects::ApplicationController
 
   def editor_variables
     @current_branch = @ref
-    @target_branch = (sanitized_new_branch_name || @ref)
+    @target_branch = params[:new_branch].present? ? sanitized_new_branch_name : @ref
 
     @file_path =
       if action_name.to_s == 'create'
diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4e4ac6689d327dafc4b7586651a5456919b9c67d
--- /dev/null
+++ b/app/controllers/projects/builds_controller.rb
@@ -0,0 +1,55 @@
+class Projects::BuildsController < Projects::ApplicationController
+  before_action :ci_project
+  before_action :build
+
+  before_action :authorize_admin_project!, except: [:show, :status]
+
+  layout "project"
+
+  def show
+    @builds = @ci_project.commits.find_by_sha(@build.sha).builds.order('id DESC')
+    @builds = @builds.where("id not in (?)", @build.id).page(params[:page]).per(20)
+    @commit = @build.commit
+
+    respond_to do |format|
+      format.html
+      format.json do
+        render json: @build.to_json(methods: :trace_html)
+      end
+    end
+  end
+
+  def retry
+    if @build.commands.blank?
+      return page_404
+    end
+
+    build = Ci::Build.retry(@build)
+
+    if params[:return_to]
+      redirect_to URI.parse(params[:return_to]).path
+    else
+      redirect_to build_path(build)
+    end
+  end
+
+  def status
+    render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
+  end
+
+  def cancel
+    @build.cancel
+
+    redirect_to build_path(@build)
+  end
+
+  private
+
+  def build
+    @build ||= ci_project.builds.unscoped.find_by!(id: params[:id])
+  end
+
+  def build_path(build)
+    namespace_project_build_path(build.gl_project.namespace, build.gl_project, build)
+  end
+end
diff --git a/app/controllers/projects/ci_services_controller.rb b/app/controllers/projects/ci_services_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6d2756eba3d10e5c22f19f89a1058230e0009d0e
--- /dev/null
+++ b/app/controllers/projects/ci_services_controller.rb
@@ -0,0 +1,49 @@
+class Projects::CiServicesController < Projects::ApplicationController
+  before_action :ci_project
+  before_action :authorize_admin_project!
+
+  layout "project_settings"
+
+  def index
+    @ci_project.build_missing_services
+    @services = @ci_project.services.reload
+  end
+
+  def edit
+    service
+  end
+
+  def update
+    if @service.update_attributes(service_params)
+      redirect_to edit_namespace_project_ci_service_path(@project, @project.namespace, @service.to_param)
+    else
+      render 'edit'
+    end
+  end
+
+  def test
+    last_build = @project.builds.last
+
+    if @service.execute(last_build)
+      message = { notice: 'We successfully tested the service' }
+    else
+      message = { alert: 'We tried to test the service but error occurred' }
+    end
+
+    redirect_to :back, message
+  end
+
+  private
+
+  def service
+    @service ||= @ci_project.services.find { |service| service.to_param == params[:id] }
+  end
+
+  def service_params
+    params.require(:service).permit(
+      :type, :active, :webhook, :notify_only_broken_builds,
+      :email_recipients, :email_only_broken_builds, :email_add_pusher,
+      :hipchat_token, :hipchat_room, :hipchat_server
+    )
+  end
+end
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 2fae5057138084f1213497fa262fe71d35db56fa..7886f3c6deb20545a6231c026eb9bbffa64dff5c 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -31,6 +31,21 @@ class Projects::CommitController < Projects::ApplicationController
     end
   end
 
+  def ci
+    @ci_commit = @project.ci_commit(@commit.sha)
+    @builds = @ci_commit.builds if @ci_commit
+    @notes_count = @commit.notes.count
+    @ci_project = @project.gitlab_ci_project
+  end
+
+  def cancel_builds
+    @ci_commit = @project.ci_commit(@commit.sha)
+    @ci_commit.builds.running_or_pending.each(&:cancel)
+
+    redirect_to ci_namespace_project_commit_path(project.namespace, project, commit.sha)
+  end
+
+
   def branches
     @branches = @project.repository.branch_names_contains(commit.id)
     @tags = @project.repository.tag_names_contains(commit.id)
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 0f89f2e88ccce26ab6b5c225ad0b269993eb82f8..4612abcbae8f75c528e5f289007c1a75b5e6e8ca 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -55,7 +55,7 @@ class Projects::IssuesController < Projects::ApplicationController
   end
 
   def show
-    @participants = @issue.participants(current_user, @project)
+    @participants = @issue.participants(current_user)
     @note = @project.notes.new(noteable: @issue)
     @notes = @issue.notes.inc_author.fresh
     @noteable = @issue
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 7570934e7277c18c0cae84997e5754bc8bfa0c62..98df6984bf7d7879ca5c4a9b0aff34dce4b42b82 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -246,7 +246,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
   end
 
   def define_show_vars
-    @participants = @merge_request.participants(current_user, @project)
+    @participants = @merge_request.participants(current_user)
 
     # Build a note object for comment form
     @note = @project.notes.new(noteable: @merge_request)
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index 5f6fbce795e950d3792d80be348e1ff724779813..d5ee6ac8663b24aadaa88818becf516764454741 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -20,7 +20,7 @@ class Projects::RawController < Projects::ApplicationController
         disposition: 'inline'
       )
     else
-      not_found!
+      render_404
     end
   end
 
diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
index 6cb6e3ef6d4412b096db084a4da945fcf29a4525..deb07a214160f396092597b6ae1127c2b4d0ed07 100644
--- a/app/controllers/projects/runners_controller.rb
+++ b/app/controllers/projects/runners_controller.rb
@@ -60,6 +60,6 @@ class Projects::RunnersController < Projects::ApplicationController
   end
 
   def runner_params
-    params.require(:runner).permit(:description, :tag_list, :contacted_at, :active)
+    params.require(:runner).permit(:description, :tag_list, :active)
   end
 end
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index 92e4bc16d9d772e91b33bd76a57e2c854be2e5af..bdcb1a3e297ee178eb58f15157f06f61db037d81 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -1,13 +1,16 @@
 # Controller for viewing a repository's file structure
 class Projects::TreeController < Projects::ApplicationController
   include ExtractsPath
+  include ActionView::Helpers::SanitizeHelper
 
   before_action :require_non_empty_project, except: [:new, :create]
   before_action :assign_ref_vars
+  before_action :assign_dir_vars, only: [:create_dir]
   before_action :authorize_download_code!
+  before_action :authorize_push_code!, only: [:create_dir]
 
   def show
-    return not_found! unless @repository.commit(@ref)
+    return render_404 unless @repository.commit(@ref)
 
     if tree.entries.empty?
       if @repository.blob_at(@commit.id, @path)
@@ -16,7 +19,7 @@ class Projects::TreeController < Projects::ApplicationController
                                       File.join(@ref, @path))
         ) and return
       elsif @path.present?
-        return not_found!
+        return render_404
       end
     end
 
@@ -26,4 +29,38 @@ class Projects::TreeController < Projects::ApplicationController
       format.js { no_cache_headers }
     end
   end
+
+  def create_dir
+    return render_404 unless @commit_params.values.all?
+
+    begin
+      result = Files::CreateDirService.new(@project, current_user, @commit_params).execute
+      message = result[:message]
+    rescue => e
+      message = e.to_s
+    end
+
+    if result && result[:status] == :success
+      flash[:notice] = "The directory has been successfully created"
+      respond_to do |format|
+        format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @dir_name)) }
+      end
+    else
+      flash[:alert] = message
+      respond_to do |format|
+        format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, @new_branch) }
+      end
+    end
+  end
+
+  def assign_dir_vars
+    @new_branch = params[:new_branch].present? ? sanitize(strip_tags(params[:new_branch])) : @ref
+    @dir_name = File.join(@path, params[:dir_name])
+    @commit_params = {
+      file_path: @dir_name,
+      current_branch: @ref,
+      target_branch: @new_branch,
+      commit_message: params[:commit_message],
+    }
+  end
 end
diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb
index 71ecc20dd95ea7fe681e5b9ed5ef378974eeb8e6..e1fe7ea21143fcc6d3131cff79026d9f6f2ebafb 100644
--- a/app/controllers/projects/uploads_controller.rb
+++ b/app/controllers/projects/uploads_controller.rb
@@ -20,7 +20,7 @@ class Projects::UploadsController < Projects::ApplicationController
   end
 
   def show
-    return not_found! if uploader.nil? || !uploader.file.exists?
+    return render_404 if uploader.nil? || !uploader.file.exists?
 
     disposition = uploader.image? ? 'inline' : 'attachment'
     send_file uploader.file.path, disposition: disposition
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index 28536e359e51c538e3bbfc8fe2bedef816eb7a73..868b05929d7404461438e8d321bb3115f3ee7400 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -10,7 +10,7 @@ class UploadsController < ApplicationController
     end
 
     unless uploader.file && uploader.file.exists?
-      return not_found!
+      return render_404
     end
 
     disposition = uploader.image? ? 'inline' : 'attachment'
@@ -21,7 +21,7 @@ class UploadsController < ApplicationController
 
   def find_model
     unless upload_model && upload_mount
-      return not_found!
+      return render_404
     end
 
     @model = upload_model.find(params[:id])
@@ -44,7 +44,7 @@ class UploadsController < ApplicationController
     return if authorized
 
     if current_user
-      not_found!
+      render_404
     else
       authenticate_user!
     end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 6aa16673d63f93eed1b1a361a2032e781aec615e..97c7e74c2944aaa2a2285bdd503a5f65d195fbe1 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -72,11 +72,15 @@ class IssuableFinder
     params[:milestone_title].present?
   end
 
+  def no_milestones?
+    milestones? && params[:milestone_title] == Milestone::None.title
+  end
+
   def milestones
     return @milestones if defined?(@milestones)
 
     @milestones =
-      if milestones? && params[:milestone_title] != Milestone::None.title
+      if milestones?
         Milestone.where(title: params[:milestone_title])
       else
         nil
@@ -183,7 +187,11 @@ class IssuableFinder
 
   def by_milestone(items)
     if milestones?
-      items = items.where(milestone_id: milestones.try(:pluck, :id))
+      if no_milestones?
+        items = items.where(milestone_id: [-1, nil])
+      else
+        items = items.where(milestone_id: milestones.try(:pluck, :id))
+      end
     end
 
     items
@@ -207,13 +215,19 @@ class IssuableFinder
 
   def by_label(items)
     if params[:label_name].present?
-      label_names = params[:label_name].split(",")
+      if params[:label_name] == Label::None.title
+        item_ids = LabelLink.where(target_type: klass.name).pluck(:target_id)
 
-      item_ids = LabelLink.joins(:label).
-        where('labels.title in (?)', label_names).
-        where(target_type: klass.name).pluck(:target_id)
+        items = items.where('id NOT IN (?)', item_ids)
+      else
+        label_names = params[:label_name].split(",")
+
+        item_ids = LabelLink.joins(:label).
+          where('labels.title in (?)', label_names).
+          where(target_type: klass.name).pluck(:target_id)
 
-      items = items.where(id: item_ids)
+        items = items.where(id: item_ids)
+      end
     end
 
     items
diff --git a/app/finders/trending_projects_finder.rb b/app/finders/trending_projects_finder.rb
index 9ea342cb26dc14ce97330ec911d9b975d8854c55..81a12403801a4447a528228d5d204dc109a904b3 100644
--- a/app/finders/trending_projects_finder.rb
+++ b/app/finders/trending_projects_finder.rb
@@ -1,13 +1,6 @@
 class TrendingProjectsFinder
-  def execute(current_user, start_date = nil)
-    start_date ||= Date.today - 1.month
-
-    projects = projects_for(current_user)
-
-    # Determine trending projects based on comments count
-    # for period of time - ex. month
-    projects.joins(:notes).where('notes.created_at > ?', start_date).
-      group("projects.id").reorder("count(notes.id) DESC")
+  def execute(current_user, start_date = 1.month.ago)
+    projects_for(current_user).trending(start_date)
   end
 
   private
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 3ab44719d9f3269010ba7006a3f222d8824b00f2..cab2278adb7f8fe3c072d378021566082f9c1d42 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -314,4 +314,8 @@ module ApplicationHelper
 
     html.html_safe
   end
+
+  def truncate_first_line(message, length = 50)
+    truncate(message.each_line.first.chomp, length: length) if message
+  end
 end
diff --git a/app/helpers/builds_helper.rb b/app/helpers/builds_helper.rb
index 626f4e2f4c0edae34f0839b9c7df24194281ecb2..1b5a2c31d74660e4fb01931bf5b4aa0135affd23 100644
--- a/app/helpers/builds_helper.rb
+++ b/app/helpers/builds_helper.rb
@@ -8,6 +8,6 @@ module BuildsHelper
   end
 
   def build_url(build)
-    ci_project_build_url(build.project, build)
+    namespace_project_build_path(build.gl_project, build.project, build)
   end
 end
diff --git a/app/helpers/ci/commits_helper.rb b/app/helpers/ci/commits_helper.rb
deleted file mode 100644
index a0df4c3d72d35d599387cb908a1a48c284cb1dab..0000000000000000000000000000000000000000
--- a/app/helpers/ci/commits_helper.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-module Ci
-  module CommitsHelper
-    def ci_commit_path(commit)
-      ci_project_commits_path(commit.project, commit)
-    end
-
-    def commit_link(commit)
-      link_to(commit.short_sha, ci_commit_path(commit))
-    end
-
-    def truncate_first_line(message, length = 50)
-      truncate(message.each_line.first.chomp, length: length) if message
-    end
-
-    def ci_commit_title(commit)
-      content_tag :span do
-        link_to(
-          simple_sanitize(commit.project.name), ci_project_path(commit.project)
-        ) + ' @ ' +
-          gitlab_commit_link(@project, @commit.sha)
-      end
-    end
-  end
-end
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index 794bdc2530ea2f1c11af7edf7137db2d90a28ae8..dbd1e26fa79b924fdb7595ed004cf5aadc243d6b 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -1,6 +1,7 @@
 module CiStatusHelper
   def ci_status_path(ci_commit)
-    ci_project_commits_path(ci_commit.project, ci_commit)
+    project = ci_commit.gl_project
+    ci_namespace_project_commit_path(project.namespace, project, ci_commit.sha)
   end
 
   def ci_status_icon(ci_commit)
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 8036303851b70aded155f62cfec35415cd0e7a82..66b18eea69990a6c90588d5e315361ecbd459e41 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -93,7 +93,10 @@ module LabelsHelper
   end
 
   def project_labels_options(project)
-    options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name])
+    labels = project.labels.to_a
+    labels.unshift(Label::None)
+    labels.unshift(Label::Any)
+    options_from_collection_for_select(labels, 'name', 'title', params[:label_name])
   end
 
   # Required for Gitlab::Markdown::LabelReferenceFilter
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 132a893e532965be442e9f11a4c18cd16a7eb52b..37a5b58cce8be8efd3ad934662b239b529cc02d4 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -30,7 +30,8 @@ module MilestonesHelper
 
     grouped_milestones = Milestones::GroupService.new(milestones).execute
     grouped_milestones.unshift(Milestone::None)
+    grouped_milestones.unshift(Milestone::Any)
 
-    options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title])
+    options_from_collection_for_select(grouped_milestones, 'name', 'title', params[:milestone_title])
   end
 end
diff --git a/app/helpers/runners_helper.rb b/app/helpers/runners_helper.rb
index 5d7d06c84903db173ea00ad3945f1f4a758d5b54..5afebab88e1bfdda1c37a113b4dacf4bb1419c6c 100644
--- a/app/helpers/runners_helper.rb
+++ b/app/helpers/runners_helper.rb
@@ -1,20 +1,16 @@
 module RunnersHelper
   def runner_status_icon(runner)
-    unless runner.contacted_at
-      return content_tag :i, nil,
-        class: "fa fa-warning-sign",
-        title: "New runner. Has not connected yet"
-    end
-
-    status =
-      if runner.active?
-        runner.contacted_at > 3.hour.ago ? :online : :offline
-      else
-        :paused
-      end
+    status = runner.status
+    case status
+    when :not_connected
+      content_tag :i, nil,
+                  class: "fa fa-warning",
+                  title: "New runner. Has not connected yet"
 
-    content_tag :i, nil,
-      class: "fa fa-circle runner-status-#{status}",
-      title: "Runner is #{status}, last contact was #{time_ago_in_words(runner.contacted_at)} ago"
+    when :online, :offline, :paused
+      content_tag :i, nil,
+                  class: "fa fa-circle runner-status-#{status}",
+                  title: "Runner is #{status}, last contact was #{time_ago_in_words(runner.contacted_at)} ago"
+    end
   end
 end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index a020b24a550f6fe75f2830b37228666fdafcc1c9..77c121ca5e851bd40b7f10956ad0dda5fa06b80d 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -135,6 +135,8 @@ class Ability
 
     def project_report_rules
       project_guest_rules + [
+        :create_commit_status,
+        :read_commit_statuses,
         :download_code,
         :fork_project,
         :create_project_snippet,
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index f35224916ed20e728593d92c1acc30d382796bb0..5f8d44148cadc3152a49c87e290214f5426e58fc 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -24,32 +24,19 @@
 #
 
 module Ci
-  class Build < ActiveRecord::Base
-    extend Ci::Model
-
+  class Build < CommitStatus
     LAZY_ATTRIBUTES = ['trace']
 
-    belongs_to :commit, class_name: 'Ci::Commit'
     belongs_to :runner, class_name: 'Ci::Runner'
     belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
-    belongs_to :user
 
     serialize :options
 
-    validates :commit, presence: true
-    validates :status, presence: true
     validates :coverage, numericality: true, allow_blank: true
     validates_presence_of :ref
 
-    scope :running, ->() { where(status: "running") }
-    scope :pending, ->() { where(status: "pending") }
-    scope :success, ->() { where(status: "success") }
-    scope :failed, ->() { where(status: "failed")  }
     scope :unstarted, ->() { where(runner_id: nil) }
-    scope :running_or_pending, ->() { where(status:[:running, :pending]) }
-    scope :latest, ->() { where(id: unscope(:select).select('max(id)').group(:name)).order(stage_idx: :asc) }
     scope :ignore_failures, ->() { where(allow_failure: false) }
-    scope :for_ref, ->(ref) { where(ref: ref) }
     scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) }
 
     acts_as_taggable
@@ -74,13 +61,14 @@ module Ci
 
       def create_from(build)
         new_build = build.dup
-        new_build.status = :pending
+        new_build.status = 'pending'
         new_build.runner_id = nil
+        new_build.trigger_request_id = nil
         new_build.save
       end
 
       def retry(build)
-        new_build = Ci::Build.new(status: :pending)
+        new_build = Ci::Build.new(status: 'pending')
         new_build.ref = build.ref
         new_build.tag = build.tag
         new_build.options = build.options
@@ -98,28 +86,7 @@ module Ci
     end
 
     state_machine :status, initial: :pending do
-      event :run do
-        transition pending: :running
-      end
-
-      event :drop do
-        transition running: :failed
-      end
-
-      event :success do
-        transition running: :success
-      end
-
-      event :cancel do
-        transition [:pending, :running] => :canceled
-      end
-
-      after_transition pending: :running do |build, transition|
-        build.update_attributes started_at: Time.now
-      end
-
       after_transition any => [:success, :failed, :canceled] do |build, transition|
-        build.update_attributes finished_at: Time.now
         project = build.project
 
         if project.web_hooks?
@@ -136,19 +103,10 @@ module Ci
           build.update_coverage
         end
       end
-
-      state :pending, value: 'pending'
-      state :running, value: 'running'
-      state :failed, value: 'failed'
-      state :success, value: 'success'
-      state :canceled, value: 'canceled'
     end
 
-    delegate :sha, :short_sha, :project,
-      to: :commit, prefix: false
-
-    def before_sha
-      Gitlab::Git::BLANK_SHA
+    def ignored?
+      failed? && allow_failure?
     end
 
     def trace_html
@@ -156,36 +114,12 @@ module Ci
       html || ''
     end
 
-    def started?
-      !pending? && !canceled? && started_at
-    end
-
-    def active?
-      running? || pending?
-    end
-
-    def complete?
-      canceled? || success? || failed?
-    end
-
-    def ignored?
-      failed? && allow_failure?
-    end
-
     def timeout
       project.timeout
     end
 
     def variables
-      yaml_variables + project_variables + trigger_variables
-    end
-
-    def duration
-      if started_at && finished_at
-        finished_at - started_at
-      elsif started_at
-        Time.now - started_at
-      end
+      predefined_variables + yaml_variables + project_variables + trigger_variables
     end
 
     def project
@@ -278,6 +212,37 @@ module Ci
       "#{dir_to_trace}/#{id}.log"
     end
 
+    def target_url
+      Gitlab::Application.routes.url_helpers.
+        namespace_project_build_url(gl_project.namespace, gl_project, self)
+    end
+
+    def cancel_url
+      if active?
+        Gitlab::Application.routes.url_helpers.
+          cancel_namespace_project_build_path(gl_project.namespace, gl_project, self)
+      end
+    end
+
+    def retry_url
+      if commands.present?
+        Gitlab::Application.routes.url_helpers.
+          retry_namespace_project_build_path(gl_project.namespace, gl_project, self)
+      end
+    end
+
+    def can_be_served?(runner)
+      (tag_list - runner.tag_list).empty?
+    end
+
+    def any_runners_online?
+      project.any_runners? { |runner| runner.active? && runner.online? && can_be_served?(runner) }
+    end
+
+    def show_warning?
+      pending? && !any_runners_online?
+    end
+
     private
 
     def yaml_variables
@@ -305,5 +270,14 @@ module Ci
         []
       end
     end
+
+    def predefined_variables
+      variables = []
+      variables << { key: :CI_BUILD_TAG, value: ref, public: true } if tag?
+      variables << { key: :CI_BUILD_NAME, value: name, public: true }
+      variables << { key: :CI_BUILD_STAGE, value: stage, public: true }
+      variables << { key: :CI_BUILD_TRIGGERED, value: 'true', public: true } if trigger_request
+      variables
+    end
   end
 end
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
index 46370034f9a30933988b20c0f441051a4b6dcd80..68864edfbbf40155b140a4ac64b22ca7dd29278e 100644
--- a/app/models/ci/commit.rb
+++ b/app/models/ci/commit.rb
@@ -20,7 +20,8 @@ module Ci
     extend Ci::Model
 
     belongs_to :gl_project, class_name: '::Project', foreign_key: :gl_project_id
-    has_many :builds, dependent: :destroy, class_name: 'Ci::Build'
+    has_many :statuses, dependent: :destroy, class_name: 'CommitStatus'
+    has_many :builds, class_name: 'Ci::Build'
     has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
 
     validates_presence_of :sha
@@ -47,7 +48,7 @@ module Ci
     end
 
     def retry
-      builds_without_retry.each do |build|
+      latest_builds.each do |build|
         Ci::Build.retry(build)
       end
     end
@@ -81,12 +82,11 @@ module Ci
     end
 
     def stage
-      running_or_pending = builds_without_retry.running_or_pending
-      running_or_pending.limit(1).pluck(:stage).first
+      running_or_pending = statuses.latest.running_or_pending.ordered
+      running_or_pending.first.try(:stage)
     end
 
     def create_builds(ref, tag, user, trigger_request = nil)
-      return if skip_ci? && trigger_request.blank?
       return unless config_processor
       config_processor.stages.any? do |stage|
         CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present?
@@ -94,7 +94,6 @@ module Ci
     end
 
     def create_next_builds(ref, tag, user, trigger_request)
-      return if skip_ci? && trigger_request.blank?
       return unless config_processor
 
       stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage)
@@ -107,61 +106,60 @@ module Ci
     end
 
     def refs
-      builds.group(:ref).pluck(:ref)
+      statuses.order(:ref).pluck(:ref).uniq
     end
 
-    def last_ref
-      builds.latest.first.try(:ref)
+    def latest_statuses
+      @latest_statuses ||= statuses.latest.to_a
     end
 
-    def builds_without_retry
-      builds.latest
+    def latest_builds
+      @latest_builds ||= builds.latest.to_a
     end
 
-    def builds_without_retry_for_ref(ref)
-      builds.for_ref(ref).latest
+    def latest_builds_for_ref(ref)
+      latest_builds.select { |build| build.ref == ref }
     end
 
-    def retried_builds
-      @retried_builds ||= (builds.order(id: :desc) - builds_without_retry)
+    def retried
+      @retried ||= (statuses.order(id: :desc) - statuses.latest)
     end
 
     def status
-      if skip_ci?
-        return 'skipped'
-      elsif yaml_errors.present?
+      if yaml_errors.present?
         return 'failed'
-      elsif builds.none?
-        return 'skipped'
-      elsif success?
-        'success'
-      elsif pending?
-        'pending'
-      elsif running?
-        'running'
-      elsif canceled?
-        'canceled'
-      else
-        'failed'
+      end
+
+      @status ||= begin
+        latest = latest_statuses
+        latest.reject! { |status| status.try(&:allow_failure?) }
+
+        if latest.none?
+          'skipped'
+        elsif latest.all?(&:success?)
+          'success'
+        elsif latest.all?(&:pending?)
+          'pending'
+        elsif latest.any?(&:running?) || latest.any?(&:pending?)
+          'running'
+        elsif latest.all?(&:canceled?)
+          'canceled'
+        else
+          'failed'
+        end
       end
     end
 
     def pending?
-      builds_without_retry.all? do |build|
-        build.pending?
-      end
+      status == 'pending'
     end
 
     def running?
-      builds_without_retry.any? do |build|
-        build.running? || build.pending?
-      end
+      status == 'running'
     end
 
     def success?
-      builds_without_retry.all? do |build|
-        build.success? || build.ignored?
-      end
+      status == 'success'
     end
 
     def failed?
@@ -169,26 +167,21 @@ module Ci
     end
 
     def canceled?
-      builds_without_retry.all? do |build|
-        build.canceled?
-      end
+      status == 'canceled'
     end
 
     def duration
-      @duration ||= builds_without_retry.select(&:duration).sum(&:duration).to_i
-    end
-
-    def duration_for_ref(ref)
-      builds_without_retry_for_ref(ref).select(&:duration).sum(&:duration).to_i
+      duration_array = latest_statuses.map(&:duration).compact
+      duration_array.reduce(:+).to_i
     end
 
     def finished_at
-      @finished_at ||= builds.order('finished_at DESC').first.try(:finished_at)
+      @finished_at ||= statuses.order('finished_at DESC').first.try(:finished_at)
     end
 
     def coverage
       if project.coverage_enabled?
-        coverage_array = builds_without_retry.map(&:coverage).compact
+        coverage_array = latest_builds.map(&:coverage).compact
         if coverage_array.size >= 1
           '%.2f' % (coverage_array.reduce(:+) / coverage_array.size)
         end
@@ -196,7 +189,7 @@ module Ci
     end
 
     def matrix_for_ref?(ref)
-      builds_without_retry_for_ref(ref).pluck(:id).size > 1
+      latest_builds_for_ref(ref).size > 1
     end
 
     def config_processor
@@ -211,13 +204,12 @@ module Ci
     end
 
     def ci_yaml_file
-      gl_project.repository.blob_at(sha, '.gitlab-ci.yml')
+      gl_project.repository.blob_at(sha, '.gitlab-ci.yml').data
     rescue
       nil
     end
 
     def skip_ci?
-      return false if builds.any?
       git_commit_message =~ /(\[ci skip\])/ if git_commit_message
     end
 
diff --git a/app/models/ci/project.rb b/app/models/ci/project.rb
index 88ba933a434c9ab55e69614d76d38d0e5b1ab9a1..ef28353a30c35b3267ad9bdaa7ff5f1a9575262b 100644
--- a/app/models/ci/project.rb
+++ b/app/models/ci/project.rb
@@ -115,12 +115,12 @@ module Ci
       web_url
     end
 
-    def any_runners?
-      if runners.active.any?
+    def any_runners?(&block)
+      if runners.active.any?(&block)
         return true
       end
 
-      shared_runners_enabled && Ci::Runner.shared.active.any?
+      shared_runners_enabled && Ci::Runner.shared.active.any?(&block)
     end
 
     def set_default_values
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 6838ccfaaab4330e58dced4b462bc249b705f6c4..02a3e9db1fa4c0efe95a7bf8ce80aeca46e1068c 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -20,6 +20,8 @@
 module Ci
   class Runner < ActiveRecord::Base
     extend Ci::Model
+
+    LAST_CONTACT_TIME = 5.minutes.ago
     
     has_many :builds, class_name: 'Ci::Build'
     has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
@@ -33,6 +35,7 @@ module Ci
     scope :shared, ->() { where(is_shared: true) }
     scope :active, ->() { where(active: true) }
     scope :paused, ->() { where(active: false) }
+    scope :online, ->() { where('contacted_at > ?', LAST_CONTACT_TIME) }
 
     acts_as_taggable
 
@@ -65,6 +68,20 @@ module Ci
       is_shared
     end
 
+    def online?
+      contacted_at && contacted_at > LAST_CONTACT_TIME
+    end
+
+    def status
+      if contacted_at.nil?
+        :not_connected
+      elsif active?
+        online? ? :online : :offline
+      else
+        :paused
+      end
+    end
+
     def belongs_to_one_project?
       runner_projects.count == 1
     end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index aff329d71fa3f29e657597531ea161bfd3c90b68..d5c50013525a8f17575bf6ae80557df1a0bf5f17 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -184,4 +184,12 @@ class Commit
   def parents
     @parents ||= Commit.decorate(super, project)
   end
+
+  def ci_commit
+    project.ci_commit(sha)
+  end
+
+  def status
+    ci_commit.try(:status) || :not_found
+  end
 end
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
new file mode 100644
index 0000000000000000000000000000000000000000..92905c618ebcd2985529ee60ae4e5fefdd625847
--- /dev/null
+++ b/app/models/commit_status.rb
@@ -0,0 +1,95 @@
+class CommitStatus < ActiveRecord::Base
+  self.table_name = 'ci_builds'
+
+  belongs_to :commit, class_name: 'Ci::Commit'
+  belongs_to :user
+
+  validates :commit, presence: true
+  validates :status, inclusion: { in: %w(pending running failed success canceled) }
+
+  validates_presence_of :name
+
+  alias_attribute :author, :user
+
+  scope :running, -> { where(status: 'running') }
+  scope :pending, -> { where(status: 'pending') }
+  scope :success, -> { where(status: 'success') }
+  scope :failed, -> { where(status: 'failed')  }
+  scope :running_or_pending, -> { where(status:[:running, :pending]) }
+  scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)) }
+  scope :ordered, -> { order(:ref, :stage_idx, :name) }
+  scope :for_ref, ->(ref) { where(ref: ref) }
+  scope :running_or_pending, -> { where(status: [:running, :pending]) }
+
+  state_machine :status, initial: :pending do
+    event :run do
+      transition pending: :running
+    end
+
+    event :drop do
+      transition running: :failed
+    end
+
+    event :success do
+      transition [:pending, :running] => :success
+    end
+
+    event :cancel do
+      transition [:pending, :running] => :canceled
+    end
+
+    after_transition pending: :running do |build, transition|
+      build.update_attributes started_at: Time.now
+    end
+
+    after_transition any => [:success, :failed, :canceled] do |build, transition|
+      build.update_attributes finished_at: Time.now
+    end
+
+    state :pending, value: 'pending'
+    state :running, value: 'running'
+    state :failed, value: 'failed'
+    state :success, value: 'success'
+    state :canceled, value: 'canceled'
+  end
+
+  delegate :sha, :short_sha, :gl_project,
+           to: :commit, prefix: false
+
+  # TODO: this should be removed with all references
+  def before_sha
+    Gitlab::Git::BLANK_SHA
+  end
+
+  def started?
+    !pending? && !canceled? && started_at
+  end
+
+  def active?
+    running? || pending?
+  end
+
+  def complete?
+    canceled? || success? || failed?
+  end
+
+  def duration
+    if started_at && finished_at
+      finished_at - started_at
+    elsif started_at
+      Time.now - started_at
+    end
+  end
+
+  def cancel_url
+    nil
+  end
+
+  def retry_url
+    nil
+  end
+
+  def show_warning?
+    false
+  end
+end
diff --git a/app/models/concerns/case_sensitivity.rb b/app/models/concerns/case_sensitivity.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fe0cea8465f628842bfe311f9bcdcbdce76d93f2
--- /dev/null
+++ b/app/models/concerns/case_sensitivity.rb
@@ -0,0 +1,28 @@
+# Concern for querying columns with specific case sensitivity handling.
+module CaseSensitivity
+  extend ActiveSupport::Concern
+
+  module ClassMethods
+    # Queries the given columns regardless of the casing used.
+    #
+    # Unlike other ActiveRecord methods this method only operates on a Hash.
+    def iwhere(params)
+      criteria   = self
+      cast_lower = Gitlab::Database.postgresql?
+
+      params.each do |key, value|
+        column = ActiveRecord::Base.connection.quote_table_name(key)
+
+        if cast_lower
+          condition = "LOWER(#{column}) = LOWER(:value)"
+        else
+          condition = "#{column} = :value"
+        end
+
+        criteria = criteria.where(condition, value: value)
+      end
+
+      criteria
+    end
+  end
+end
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 5b0ae41164200ed37a0eedfb994cacecdbcd4378..b34def66d2e260955609e26e8a0251454da5eb0d 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -41,55 +41,49 @@ module Mentionable
     self
   end
 
-  # Determine whether or not a cross-reference Note has already been created between this Mentionable and
-  # the specified target.
-  def has_mentioned?(target)
-    SystemNoteService.cross_reference_exists?(target, local_reference)
+  def all_references(current_user = self.author, text = self.mentionable_text)
+    ext = Gitlab::ReferenceExtractor.new(self.project, current_user)
+    ext.analyze(text)
+    ext
   end
 
   def mentioned_users(current_user = nil)
-    return [] if mentionable_text.blank?
-
-    ext = Gitlab::ReferenceExtractor.new(self.project, current_user)
-    ext.analyze(mentionable_text)
-    ext.users.uniq
+    all_references(current_user).users.uniq
   end
 
   # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference.
-  def references(p = project, current_user = self.author, text = mentionable_text)
+  def referenced_mentionables(current_user = self.author, text = self.mentionable_text)
     return [] if text.blank?
 
-    ext = Gitlab::ReferenceExtractor.new(p, current_user)
-    ext.analyze(text)
-
-    (ext.issues + ext.merge_requests + ext.commits).uniq - [local_reference]
+    refs = all_references(current_user, text)
+    (refs.issues + refs.merge_requests + refs.commits).uniq - [local_reference]
   end
 
   # Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+.
-  def create_cross_references!(p = project, a = author, without = [])
-    refs = references(p)
-
+  def create_cross_references!(author = self.author, without = [], text = self.mentionable_text)
+    refs = referenced_mentionables(author, text)
+    
     # We're using this method instead of Array diffing because that requires
     # both of the object's `hash` values to be the same, which may not be the
     # case for otherwise identical Commit objects.
-    refs.reject! { |ref| without.include?(ref) }
+    refs.reject! { |ref| without.include?(ref) || cross_reference_exists?(ref) }
 
     refs.each do |ref|
-      SystemNoteService.cross_reference(ref, local_reference, a)
+      SystemNoteService.cross_reference(ref, local_reference, author)
     end
   end
 
   # When a mentionable field is changed, creates cross-reference notes that
   # don't already exist
-  def create_new_cross_references!(p = project, a = author)
+  def create_new_cross_references!(author = self.author)
     changes = detect_mentionable_changes
 
     return if changes.empty?
 
     original_text = changes.collect { |_, vals| vals.first }.join(' ')
 
-    preexisting = references(p, self.author, original_text)
-    create_cross_references!(p, a, preexisting)
+    preexisting = referenced_mentionables(author, original_text)
+    create_cross_references!(author, preexisting)
   end
 
   private
@@ -111,4 +105,10 @@ module Mentionable
     # Only include changed fields that are mentionable
     source.select { |key, val| mentionable.include?(key) }
   end
+  
+  # Determine whether or not a cross-reference Note has already been created between this Mentionable and
+  # the specified target.
+  def cross_reference_exists?(target)
+    SystemNoteService.cross_reference_exists?(target, local_reference)
+  end
 end
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 7c9597333dd943269a8c83b0e4eeb9bd10930555..ffc874357fdf4b3c101f4e5a97cba5e7cab6f549 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -37,8 +37,8 @@ module Participable
 
   # Be aware that this method makes a lot of sql queries.
   # Save result into variable if you are going to reuse it inside same request
-  def participants(current_user = self.author, project = self.project)
-    participants = self.class.participant_attrs.flat_map do |attr|
+  def participants(current_user = self.author)
+    self.class.participant_attrs.flat_map do |attr|
       meth = method(attr)
 
       value =
@@ -48,28 +48,22 @@ module Participable
           meth.call
         end
 
-      participants_for(value, current_user, project)
-    end.compact.uniq
-
-    if project
-      participants.select! do |user|
-        user.can?(:read_project, project)
-      end
+      participants_for(value, current_user)
+    end.compact.uniq.select do |user|
+      user.can?(:read_project, self.project)
     end
-
-    participants
   end
 
   private
 
-  def participants_for(value, current_user = nil, project = nil)
+  def participants_for(value, current_user = nil)
     case value
     when User
       [value]
     when Enumerable, ActiveRecord::Relation
-      value.flat_map { |v| participants_for(v, current_user, project) }
+      value.flat_map { |v| participants_for(v, current_user) }
     when Participable
-      value.participants(current_user, project)
+      value.participants(current_user)
     end
   end
 end
diff --git a/app/models/generic_commit_status.rb b/app/models/generic_commit_status.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fa54e3540d07bd99637c76b65d7b53ba4acc58c5
--- /dev/null
+++ b/app/models/generic_commit_status.rb
@@ -0,0 +1,15 @@
+class GenericCommitStatus < CommitStatus
+  before_validation :set_default_values
+
+  # GitHub compatible API
+  alias_attribute :context, :name
+
+  def set_default_values
+    self.context ||= 'default'
+    self.stage ||= 'external'
+  end
+
+  def tags
+    [:external]
+  end
+end
diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb
index ab055f6b80bf785341fae04cc03cb0692c485811..1dd2be68ebf404bcb4f82b48785ef704d2521d0a 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/group_milestone.rb
@@ -1,5 +1,7 @@
 class GroupMilestone
 
+  alias_attribute :name, :title
+
   def initialize(title, milestones)
     @title = title
     @milestones = milestones
diff --git a/app/models/label.rb b/app/models/label.rb
index 4a22bd53400480af0f2e981f06393565c8de2a61..1bb4b5f55cfa6e89f32e3d354e0abd9b3ad6c83a 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -12,6 +12,11 @@
 
 class Label < ActiveRecord::Base
   include Referable
+  # Represents a "No Label" state used for filtering Issues and Merge
+  # Requests that have no label assigned.
+  LabelStruct = Struct.new(:title, :name)
+  None = LabelStruct.new('No Label', 'No Label')
+  Any = LabelStruct.new('Any', '')
 
   DEFAULT_COLOR = '#428BCA'
 
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index eb468c6cd53b162140dbd58c987c9cd1740f72be..c83b15c7d392d355cf166a7358d21f6aac88d5d1 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -227,7 +227,7 @@ class MergeRequest < ActiveRecord::Base
   end
 
   def work_in_progress?
-    title =~ /\A\[?WIP\]?:? /i
+    !!(title =~ /\A\[?WIP\]?:? /i)
   end
 
   def mergeable?
@@ -275,7 +275,8 @@ class MergeRequest < ActiveRecord::Base
     attrs = {
       source: source_project.hook_attrs,
       target: target_project.hook_attrs,
-      last_commit: nil
+      last_commit: nil,
+      work_in_progress: work_in_progress?
     }
 
     unless last_commit.nil?
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index d979a35084b8b1608bbd541c1f4e45c88a76d506..84acba30b6bd1b1ef4f4a483c09dc2ec367c93cb 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -16,7 +16,9 @@
 class Milestone < ActiveRecord::Base
   # Represents a "No Milestone" state used for filtering Issues and Merge
   # Requests that have no milestone assigned.
-  None = Struct.new(:title).new('No Milestone')
+  MilestoneStruct = Struct.new(:title, :name)
+  None = MilestoneStruct.new('No Milestone', 'No Milestone')
+  Any = MilestoneStruct.new('Any', '')
 
   include InternalId
   include Sortable
@@ -47,6 +49,8 @@ class Milestone < ActiveRecord::Base
     state :active
   end
 
+  alias_attribute :name, :title
+
   class << self
     def search(query)
       query = "%#{query}%"
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index bc8525df5a5097bdf4f793057251a0e15fc182c5..5782e649f8be15100eadec612886b6ea2f26e5ae 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -118,6 +118,8 @@ class Namespace < ActiveRecord::Base
     gitlab_shell.add_namespace(path_was)
 
     if gitlab_shell.mv_namespace(path_was, path)
+      Gitlab::UploadsTransfer.new.rename_namespace(path_was, path)
+
       # If repositories moved successfully we need to
       # send update instructions to users.
       # However we cannot allow rollback since we moved namespace dir
diff --git a/app/models/note.rb b/app/models/note.rb
index de3b6df88f7ce8ef07d6c4e8c7db267f2ca28fd3..ee0c14598f3aca97b1a9aaecce0922fc8d7e202e 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -62,7 +62,6 @@ class Note < ActiveRecord::Base
 
   serialize :st_diff
   before_create :set_diff, if: ->(n) { n.line_code.present? }
-  after_update :set_references
 
   class << self
     def discussions_from_notes(notes)
@@ -333,15 +332,13 @@ class Note < ActiveRecord::Base
   end
 
   def noteable_type_name
-    if noteable_type.present?
-      noteable_type.downcase
-    end
+    noteable_type.downcase if noteable_type.present?
   end
 
   # FIXME: Hack for polymorphic associations with STI
   #        For more information visit http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations
-  def noteable_type=(sType)
-    super(sType.to_s.classify.constantize.base_class.to_s)
+  def noteable_type=(noteable_type)
+    super(noteable_type.to_s.classify.constantize.base_class.to_s)
   end
 
   # Reset notes events cache
@@ -357,10 +354,6 @@ class Note < ActiveRecord::Base
     Event.reset_event_cache_for(self)
   end
 
-  def set_references
-    create_new_cross_references!(project, author)
-  end
-
   def system?
     read_attribute(:system)
   end
diff --git a/app/models/project.rb b/app/models/project.rb
index bb47b9abb03907a356cc86ad3d199bb0e364e510..cd30467fae33cc7b6e3096ae851439cc64d72c2f 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -40,6 +40,7 @@ class Project < ActiveRecord::Base
   include Referable
   include Sortable
   include AfterCommitQueue
+  include CaseSensitivity
 
   extend Gitlab::ConfigHelper
   extend Enumerize
@@ -235,13 +236,18 @@ class Project < ActiveRecord::Base
     end
 
     def find_with_namespace(id)
-      return nil unless id.include?('/')
-
-      id = id.split('/')
-      namespace = Namespace.by_path(id.first)
-      return nil unless namespace
-
-      where(namespace_id: namespace.id).where("LOWER(projects.path) = :path", path: id.second.downcase).first
+      namespace_path, project_path = id.split('/')
+
+      return nil if !namespace_path || !project_path
+
+      # Use of unscoped ensures we're not secretly adding any ORDER BYs, which
+      # have a negative impact on performance (and aren't needed for this
+      # query).
+      unscoped.
+        joins(:namespace).
+        iwhere('namespaces.path' => namespace_path).
+        iwhere('projects.path' => project_path).
+        take
     end
 
     def visibility_levels
@@ -260,6 +266,20 @@ class Project < ActiveRecord::Base
       name_pattern = Gitlab::Regex::NAMESPACE_REGEX_STR
       %r{(?<project>#{name_pattern}/#{name_pattern})}
     end
+
+    def trending(since = 1.month.ago)
+      # By counting in the JOIN we don't expose the GROUP BY to the outer query.
+      # This means that calls such as "any?" and "count" just return a number of
+      # the total count, instead of the counts grouped per project as a Hash.
+      join_body = "INNER JOIN (
+        SELECT project_id, COUNT(*) AS amount
+        FROM notes
+        WHERE created_at >= #{sanitize(since)}
+        GROUP BY project_id
+      ) join_note_counts ON projects.id = join_note_counts.project_id"
+
+      joins(join_body).reorder('join_note_counts.amount DESC')
+    end
   end
 
   def team
@@ -636,6 +656,8 @@ class Project < ActiveRecord::Base
       # db changes in order to prevent out of sync between db and fs
       raise Exception.new('repository cannot be renamed')
     end
+
+    Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.path)
   end
 
   def hook_attrs
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index d8aedbd2ab48c86726ccd7c0e472af2133859971..5f5255ab48727398a285a8d2247b222189de587a 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -40,12 +40,19 @@ class BambooService < CiService
   attr_accessor :response
 
   after_save :compose_service_hook, if: :activated?
+  before_update :reset_password
 
   def compose_service_hook
     hook = service_hook || build_service_hook
     hook.save
   end
 
+  def reset_password
+    if prop_updated?(:bamboo_url)
+      self.password = nil
+    end
+  end
+
   def title
     'Atlassian Bamboo CI'
   end
diff --git a/app/models/project_services/ci/hip_chat_message.rb b/app/models/project_services/ci/hip_chat_message.rb
index 0bf448d47f27f27c37c8b17ddab8dc2e8498f8cd..cbf325cc5255af0193bbb25155db43de7fe91767 100644
--- a/app/models/project_services/ci/hip_chat_message.rb
+++ b/app/models/project_services/ci/hip_chat_message.rb
@@ -11,7 +11,7 @@ module Ci
     def to_s
       lines = Array.new
       lines.push("<a href=\"#{ci_project_url(project)}\">#{project.name}</a> - ")
-      lines.push("<a href=\"#{ci_project_commits_url(project, commit.sha)}\">Commit ##{commit.id}</a></br>")
+      lines.push("<a href=\"#{ci_namespace_project_commit_url(commit.gl_project.namespace, commit.gl_project, commit.sha)}\">Commit ##{commit.id}</a></br>")
       lines.push("#{commit.short_sha} #{commit.git_author_name} - #{commit.git_commit_message}</br>")
       lines.push("#{humanized_status(commit_status)} in #{commit.duration} second(s).")
       lines.join('')
diff --git a/app/models/project_services/ci/hip_chat_service.rb b/app/models/project_services/ci/hip_chat_service.rb
index 0e6e97394bc67c954e2048a1f206cf9fdcf5905e..f17993d9f3bc7df6451f1fd2c3d801cfad4b231e 100644
--- a/app/models/project_services/ci/hip_chat_service.rb
+++ b/app/models/project_services/ci/hip_chat_service.rb
@@ -49,7 +49,7 @@ module Ci
 
       commit = build.commit
       return unless commit
-      return unless commit.builds_without_retry.include? build
+      return unless commit.latest_builds.include? build
 
       case commit.status.to_sym
       when :failed
diff --git a/app/models/project_services/ci/mail_service.rb b/app/models/project_services/ci/mail_service.rb
index 11a2743f9693a6b41ed3aed7bb33e19e2c8201d0..fd1933010015022130be19cefe1a3e36500ea9bf 100644
--- a/app/models/project_services/ci/mail_service.rb
+++ b/app/models/project_services/ci/mail_service.rb
@@ -48,7 +48,7 @@ module Ci
       # it doesn't make sense to send emails for retried builds
       commit = build.commit
       return unless commit
-      return unless commit.builds_without_retry.include?(build)
+      return unless commit.latest_builds.include?(build)
 
       case build.status.to_sym
       when :failed
diff --git a/app/models/project_services/ci/slack_message.rb b/app/models/project_services/ci/slack_message.rb
index a89c01517b73e5b2be4d2962c46457627a62674b..dc050a3fc59973a8890e5f6e09daa833af3931e4 100644
--- a/app/models/project_services/ci/slack_message.rb
+++ b/app/models/project_services/ci/slack_message.rb
@@ -23,12 +23,12 @@ module Ci
     def attachments
       fields = []
 
-      commit.builds_without_retry.each do |build|
+      commit.latest_builds.each do |build|
         next if build.allow_failure?
         next unless build.failed?
         fields << {
           title: build.name,
-          value: "Build <#{ci_project_build_url(project, build)}|\##{build.id}> failed in #{build.duration.to_i} second(s)."
+          value: "Build <#{namespace_project_build_url(build.gl_project.namespace, build.gl_project, build)}|\##{build.id}> failed in #{build.duration.to_i} second(s)."
         }
       end
 
@@ -45,7 +45,7 @@ module Ci
 
     def attachment_message
       out = "<#{ci_project_url(project)}|#{project_name}>: "
-      out << "Commit <#{ci_project_commits_url(project, commit.sha)}|\##{commit.id}> "
+      out << "Commit <#{ci_namespace_project_commit_url(commit.gl_project.namespace, commit.gl_project, commit.sha)}|\##{commit.id}> "
       out << "(<#{commit_sha_link}|#{commit.short_sha}>) "
       out << "of <#{commit_ref_link}|#{commit.ref}> "
       out << "by #{commit.git_author_name} " if commit.git_author_name
diff --git a/app/models/project_services/ci/slack_service.rb b/app/models/project_services/ci/slack_service.rb
index 76db573dc17a52b7e5b0ab63dd58e2b09ba3ee62..ee8e49888263c31d1daa95a07c785feaf587576e 100644
--- a/app/models/project_services/ci/slack_service.rb
+++ b/app/models/project_services/ci/slack_service.rb
@@ -48,7 +48,7 @@ module Ci
 
       commit = build.commit
       return unless commit
-      return unless commit.builds_without_retry.include?(build)
+      return unless commit.latest_builds.include?(build)
 
       case commit.status.to_sym
       when :failed
diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb
index b63a75cf3afb1a0d61f25bba43d7c197dba20320..4dcd16ede3a29d5cb835b51860177747068b316c 100644
--- a/app/models/project_services/gitlab_ci_service.rb
+++ b/app/models/project_services/gitlab_ci_service.rb
@@ -71,7 +71,7 @@ class GitlabCiService < CiService
 
   def build_page(sha, ref)
     if project.gitlab_ci_project.present?
-      ci_project_commits_url(project.gitlab_ci_project, sha)
+      ci_namespace_project_commit_url(project.namespace, project, sha)
     end
   end
 
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index 3c002a1634b8c9535e577f829145e27f1c224c9b..fb11cad352ed014e3ac818a6bb2cbbf3c24d04ac 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -37,12 +37,19 @@ class TeamcityService < CiService
   attr_accessor :response
 
   after_save :compose_service_hook, if: :activated?
+  before_update :reset_password
 
   def compose_service_hook
     hook = service_hook || build_service_hook
     hook.save
   end
 
+  def reset_password
+    if prop_updated?(:teamcity_url)
+      self.password = nil
+    end
+  end
+
   def title
     'JetBrains TeamCity CI'
   end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 2c5ab62d22c38466a95f5212683ee01f388e61a9..8b51602bc2363c306ce323b13644633fcbc15013 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -373,11 +373,25 @@ class Repository
     @root_ref ||= raw_repository.root_ref
   end
 
-  def commit_file(user, path, content, message, branch)
+  def commit_dir(user, path, message, branch)
     commit_with_hooks(user, branch) do |ref|
-      path[0] = '' if path[0] == '/'
+      committer = user_to_committer(user)
+      options = {}
+      options[:committer] = committer
+      options[:author] = committer
+
+      options[:commit] = {
+        message: message,
+        branch: ref,
+      }
+
+      raw_repository.mkdir(path, options)
+    end
+  end
 
-      committer = user_to_comitter(user)
+  def commit_file(user, path, content, message, branch, update)
+    commit_with_hooks(user, branch) do |ref|
+      committer = user_to_committer(user)
       options = {}
       options[:committer] = committer
       options[:author] = committer
@@ -388,7 +402,8 @@ class Repository
 
       options[:file] = {
         content: content,
-        path: path
+        path: path,
+        update: update
       }
 
       Gitlab::Git::Blob.commit(raw_repository, options)
@@ -397,9 +412,7 @@ class Repository
 
   def remove_file(user, path, message, branch)
     commit_with_hooks(user, branch) do |ref|
-      path[0] = '' if path[0] == '/'
-
-      committer = user_to_comitter(user)
+      committer = user_to_committer(user)
       options = {}
       options[:committer] = committer
       options[:author] = committer
@@ -416,7 +429,7 @@ class Repository
     end
   end
 
-  def user_to_comitter(user)
+  def user_to_committer(user)
     {
       email: user.email,
       name: user.name,
diff --git a/app/models/service.rb b/app/models/service.rb
index 60fcc9d2857a50dfdff4a9cddc51ab62b1d3b3fc..7e845d565b1c4c7cdcc712d89621b49d2f37885a 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -117,6 +117,15 @@ class Service < ActiveRecord::Base
     end
   end
 
+  # ActiveRecord does not provide a mechanism to track changes in serialized keys.
+  # This is why we need to perform extra query to do it mannually.
+  def prop_updated?(prop_name)
+    relation_name = self.type.underscore
+    previous_value = project.send(relation_name).send(prop_name)
+    return false if previous_value.nil?
+    previous_value != send(prop_name)
+  end
+
   def async_execute(data)
     return unless supported_events.include?(data[:object_kind])
 
diff --git a/app/services/ci/create_commit_service.rb b/app/services/ci/create_commit_service.rb
index fc1ae5774d561b6c96b8cd3f4f3bceaec2bfd997..479a2d6defc5e28b722512d02d9621178f83c8bd 100644
--- a/app/services/ci/create_commit_service.rb
+++ b/app/services/ci/create_commit_service.rb
@@ -17,8 +17,10 @@ module Ci
 
       tag = origin_ref.start_with?('refs/tags/')
       commit = project.gl_project.ensure_ci_commit(sha)
-      commit.update_committed!
-      commit.create_builds(ref, tag, user)
+      unless commit.skip_ci?
+        commit.update_committed!
+        commit.create_builds(ref, tag, user)
+      end
 
       commit
     end
diff --git a/app/services/ci/register_build_service.rb b/app/services/ci/register_build_service.rb
index 71b61bbe389bd957b28c318c31fa0c52f65f7b65..7beb098659c44f70a2e865133fa64e7b85832d26 100644
--- a/app/services/ci/register_build_service.rb
+++ b/app/services/ci/register_build_service.rb
@@ -17,7 +17,7 @@ module Ci
       builds = builds.order('created_at ASC')
 
       build = builds.find do |build|
-        (build.tag_list - current_runner.tag_list).empty?
+        build.can_be_served?(current_runner)
       end
 
 
diff --git a/app/services/files/create_dir_service.rb b/app/services/files/create_dir_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..71272fb57075e0be96b0e702585f4564cbcced5a
--- /dev/null
+++ b/app/services/files/create_dir_service.rb
@@ -0,0 +1,9 @@
+require_relative "base_service"
+
+module Files
+  class CreateDirService < Files::BaseService
+    def commit
+      repository.commit_dir(current_user, @file_path, @commit_message, @target_branch)
+    end
+  end
+end
diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb
index ffbb59932794d865814ea2afc82d135c6894620c..c8e3a910bbade941f73101bc168579d273c45534 100644
--- a/app/services/files/create_service.rb
+++ b/app/services/files/create_service.rb
@@ -3,7 +3,7 @@ require_relative "base_service"
 module Files
   class CreateService < Files::BaseService
     def commit
-      repository.commit_file(current_user, @file_path, @file_content, @commit_message, @target_branch)
+      repository.commit_file(current_user, @file_path, @file_content, @commit_message, @target_branch, false)
     end
 
     def validate
diff --git a/app/services/files/update_service.rb b/app/services/files/update_service.rb
index a20903c6f02c13e8f4e014a56ce307fe1d829c3d..1960dc7d949c1abb2612d024227da98050a1c5e9 100644
--- a/app/services/files/update_service.rb
+++ b/app/services/files/update_service.rb
@@ -3,7 +3,7 @@ require_relative "base_service"
 module Files
   class UpdateService < Files::BaseService
     def commit
-      repository.commit_file(current_user, @file_path, @file_content, @commit_message, @target_branch)
+      repository.commit_file(current_user, @file_path, @file_content, @commit_message, @target_branch, true)
     end
   end
 end
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index f9a8265d2d4d191a2cb86afcec4ec39dfca7d253..81d47602f13cd2fc8ed04c8d0481fdb4cc1fddcc 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -74,48 +74,30 @@ class GitPushService
   def process_commit_messages(ref)
     is_default_branch = is_default_branch?(ref)
 
-    @push_commits.each do |commit|
-      # Close issues if these commits were pushed to the project's default branch and the commit message matches the
-      # closing regex. Exclude any mentioned Issues from cross-referencing even if the commits are being pushed to
-      # a different branch.
-      issues_to_close = commit.closes_issues(user)
+    authors = Hash.new do |hash, commit|
+      email = commit.author_email
+      return hash[email] if hash.has_key?(email)
 
-      # Load commit author only if needed.
-      # For push with 1k commits it prevents 900+ requests in database
-      author = nil
+      hash[email] = commit_user(commit)
+    end
 
+    @push_commits.each do |commit|
       # Keep track of the issues that will be actually closed because they are on a default branch.
       # Hence, when creating cross-reference notes, the not-closed issues (on non-default branches)
       # will also have cross-reference.
-      actually_closed_issues = []
-
-      if issues_to_close.present? && is_default_branch
-        author ||= commit_user(commit)
-        actually_closed_issues = issues_to_close
-        issues_to_close.each do |issue|
-          Issues::CloseService.new(project, author, {}).execute(issue, commit)
+      closed_issues = []
+
+      if is_default_branch
+        # Close issues if these commits were pushed to the project's default branch and the commit message matches the
+        # closing regex. Exclude any mentioned Issues from cross-referencing even if the commits are being pushed to
+        # a different branch.
+        closed_issues = commit.closes_issues(user)
+        closed_issues.each do |issue|
+          Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit)
         end
       end
 
-      if project.default_issues_tracker?
-        create_cross_reference_notes(commit, actually_closed_issues)
-      end
-    end
-  end
-
-  def create_cross_reference_notes(commit, issues_to_close)
-    # Create cross-reference notes for any other references than those given in issues_to_close.
-    # Omit any issues that were referenced in an issue-closing phrase, or have already been
-    # mentioned from this commit (probably from this commit being pushed to a different branch).
-    refs = commit.references(project, user) - issues_to_close
-    refs.reject! { |r| commit.has_mentioned?(r) }
-
-    if refs.present?
-      author ||= commit_user(commit)
-
-      refs.each do |r|
-        SystemNoteService.cross_reference(r, commit, author)
-      end
+      commit.create_cross_references!(authors[commit], closed_issues)
     end
   end
 
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index 1ea4b72216c6a2e9edeaa682c43b4da8b1e21686..bcb380d3215da95c3b07a1f38105283a8b620be6 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -10,7 +10,7 @@ module Issues
         issue.update_attributes(label_ids: label_params)
         notification_service.new_issue(issue, current_user)
         event_service.open_issue(issue, current_user)
-        issue.create_cross_references!(issue.project, current_user)
+        issue.create_cross_references!(current_user)
         execute_hooks(issue, 'open')
       end
 
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index 2fc6ef7f35642913776680d7e9283bd1d9a21c65..2b5426ad4528f3d33b503840cc4b9c62c88e21be 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -35,7 +35,7 @@ module Issues
           create_title_change_note(issue, issue.previous_changes['title'].first)
         end
 
-        issue.create_new_cross_references!(issue.project, current_user)
+        issue.create_new_cross_references!
         execute_hooks(issue, 'update')
       end
 
diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb
index 9651b16462cb61b2225111e1b1c6c6a99ac0b98d..009d5a6867efab83a9065e9fcc062683dfcc446a 100644
--- a/app/services/merge_requests/create_service.rb
+++ b/app/services/merge_requests/create_service.rb
@@ -18,7 +18,7 @@ module MergeRequests
         merge_request.update_attributes(label_ids: label_params)
         event_service.open_mr(merge_request, current_user)
         notification_service.new_merge_request(merge_request, current_user)
-        merge_request.create_cross_references!(merge_request.project, current_user)
+        merge_request.create_cross_references!(current_user)
         execute_hooks(merge_request)
       end
 
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index fcc0f2a6a8d33d9996c180040226f77481b4017e..7963af127e1c61c92fc5361518fef0e4dd7c43bb 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -29,7 +29,7 @@ module MergeRequests
     private
 
     def commit
-      committer = repository.user_to_comitter(current_user)
+      committer = repository.user_to_committer(current_user)
 
       options = {
         message: commit_message,
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 25d79e22e395c9182f508621f7666d05ee63751b..ebbe0af803ba60bc069d7ce10874f18708180ab2 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -59,7 +59,7 @@ module MergeRequests
           merge_request.mark_as_unchecked
         end
 
-        merge_request.create_new_cross_references!(merge_request.project, current_user)
+        merge_request.create_new_cross_references!
         execute_hooks(merge_request, 'update')
       end
 
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 482c0444049bdef61d8c8fab5e4b0fac8779a265..2001dc89c3332fbbf91770d2dc31aefb7d244eb9 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -11,13 +11,7 @@ module Notes
         # Skip system notes, like status changes and cross-references.
         unless note.system
           event_service.leave_note(note, note.author)
-
-          # Create a cross-reference note if this Note contains GFM that names an
-          # issue, merge request, or commit.
-          note.references.each do |mentioned|
-            SystemNoteService.cross_reference(mentioned, note.noteable, note.author)
-          end
-
+          note.create_cross_references!
           execute_hooks(note)
         end
       end
diff --git a/app/services/notes/update_service.rb b/app/services/notes/update_service.rb
index c22a9333ef6889d9f36a1992a9b675b5cb7d92da..6c2f08e5963c51e0e2c2f4b44490e7edb638f777 100644
--- a/app/services/notes/update_service.rb
+++ b/app/services/notes/update_service.rb
@@ -4,7 +4,7 @@ module Notes
       return note unless note.editable?
 
       note.update_attributes(params.merge(updated_by: current_user))
-
+      note.create_new_cross_references!
       note.reset_events_cache
 
       note
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index c327c244f0d51688a2c1e31b8022ddab02d5ab4e..64ea6dd42eb8db8a88d90cd045fdd607c14c93d7 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -27,6 +27,7 @@ module Projects
     def transfer(project, new_namespace)
       Project.transaction do
         old_path = project.path_with_namespace
+        old_namespace = project.namespace
         new_path = File.join(new_namespace.try(:path) || '', project.path)
 
         if Project.where(path: project.path, namespace_id: new_namespace.try(:id)).present?
@@ -51,6 +52,9 @@ module Projects
         # clear project cached events
         project.reset_events_cache
 
+        # Move uploads
+        Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path)
+
         true
       end
     end
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index 60235b6be2ab1abe4e51058d721e02671860f9b6..9a5fe4af9dde7e93b9c298018867b9a52309c15f 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -54,6 +54,7 @@ class SystemHooksService
       data.merge!({
         project_name: model.project.name,
         project_path: model.project.path,
+        project_path_with_namespace: model.project.path_with_namespace,
         project_id: model.project.id,
         user_name: model.user.name,
         user_email: model.user.email,
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
index f9673abbfe8a5d0f1ea0d4b6a176c2be373a4128..e82115858342f4af270fa2d474753a52ed2f2829 100644
--- a/app/uploaders/file_uploader.rb
+++ b/app/uploaders/file_uploader.rb
@@ -26,7 +26,7 @@ class FileUploader < CarrierWave::Uploader::Base
   end
 
   def secure_url
-    File.join(Gitlab.config.gitlab.url, @project.path_with_namespace, "uploads", @secret, file.filename)
+    File.join("/uploads", @secret, file.filename)
   end
 
   def file_storage?
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index e3698ac1c46cbf50405fcaf51dec9e1001de5e9e..bc08458312c4b74b5ef4c0804d3f97f5ee624be7 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -32,7 +32,7 @@
       %hr
       = form_tag admin_users_path, method: :get, class: 'form-inline' do
         .form-group
-          = search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control'
+          = search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control', spellcheck: false
           = hidden_field_tag "filter", params[:filter]
         = button_tag class: 'btn btn-primary' do
           %i.fa.fa-search
@@ -54,19 +54,19 @@
               %b.caret
             %ul.dropdown-menu
               %li
-                = link_to admin_users_path(sort: sort_value_name) do
+                = link_to admin_users_path(sort: sort_value_name, filter: params[:filter]) do
                   = sort_title_name
-                = link_to admin_users_path(sort: sort_value_recently_signin) do
+                = link_to admin_users_path(sort: sort_value_recently_signin, filter: params[:filter]) do
                   = sort_title_recently_signin
-                = link_to admin_users_path(sort: sort_value_oldest_signin) do
+                = link_to admin_users_path(sort: sort_value_oldest_signin, filter: params[:filter]) do
                   = sort_title_oldest_signin
-                = link_to admin_users_path(sort: sort_value_recently_created) do
+                = link_to admin_users_path(sort: sort_value_recently_created, filter: params[:filter]) do
                   = sort_title_recently_created
-                = link_to admin_users_path(sort: sort_value_oldest_created) do
+                = link_to admin_users_path(sort: sort_value_oldest_created, filter: params[:filter]) do
                   = sort_title_oldest_created
-                = link_to admin_users_path(sort: sort_value_recently_updated) do
+                = link_to admin_users_path(sort: sort_value_recently_updated, filter: params[:filter]) do
                   = sort_title_recently_updated
-                = link_to admin_users_path(sort: sort_value_oldest_updated) do
+                = link_to admin_users_path(sort: sort_value_oldest_updated, filter: params[:filter]) do
                   = sort_title_oldest_updated
 
           = link_to 'New User', new_admin_user_path, class: "btn btn-new btn-sm"
diff --git a/app/views/ci/admin/builds/_build.html.haml b/app/views/ci/admin/builds/_build.html.haml
index 778d51d03be94e31a7f597e005f79c0fba683fcf..2df5871321404bd3ed5ecb03418e6ef8e2326f7c 100644
--- a/app/views/ci/admin/builds/_build.html.haml
+++ b/app/views/ci/admin/builds/_build.html.haml
@@ -1,14 +1,16 @@
+- gl_project = build.project.gl_project
 - if build.commit && build.project
   %tr.build
     %td.build-link
-      = link_to ci_project_build_url(build.project, build) do
+      = link_to namespace_project_build_path(gl_project.namespace, gl_project, build) do
         %strong #{build.id}
 
     %td.status
       = ci_status_with_icon(build.status)
 
     %td.commit-link
-      = commit_link(build.commit)
+      = link_to ci_status_path(build.commit) do
+        %strong #{build.commit.short_sha}
 
     %td.runner
       - if build.runner
diff --git a/app/views/ci/admin/runners/index.html.haml b/app/views/ci/admin/runners/index.html.haml
index b9d6703ff4104d9e5381b87139c1dee98a2781f4..01ce81b44764d8dd4e45b3aea5209d25cd0e50b4 100644
--- a/app/views/ci/admin/runners/index.html.haml
+++ b/app/views/ci/admin/runners/index.html.haml
@@ -27,7 +27,7 @@
   .pull-left
     = form_tag ci_admin_runners_path, id: 'runners-search', class: 'form-inline', method: :get do
       .form-group
-        = search_field_tag :search, params[:search], class: 'form-control', placeholder: 'Runner description or token'
+        = search_field_tag :search, params[:search], class: 'form-control', placeholder: 'Runner description or token', spellcheck: false
       = submit_tag 'Search', class: 'btn'
 
   .pull-right.light
diff --git a/app/views/ci/admin/runners/show.html.haml b/app/views/ci/admin/runners/show.html.haml
index 09905e0eb47d02f9d83418f9ffc48c53c5e75080..92787b2e6ac933b0d7dae3f9e2388dde4e068f41 100644
--- a/app/views/ci/admin/runners/show.html.haml
+++ b/app/views/ci/admin/runners/show.html.haml
@@ -76,7 +76,7 @@
         %td
           = form_tag ci_admin_runner_path(@runner), id: 'runner-projects-search', class: 'form-inline', method: :get do
             .form-group
-              = search_field_tag :search, params[:search], class: 'form-control'
+              = search_field_tag :search, params[:search], class: 'form-control', spellcheck: false
             = submit_tag 'Search', class: 'btn'
 
         %td
@@ -96,6 +96,7 @@
     %table.builds.runner-builds
       %thead
         %tr
+          %th Build ID
           %th Status
           %th Project
           %th Commit
@@ -103,6 +104,11 @@
 
       - @builds.each do |build|
         %tr.build
+          %td.id
+            - gl_project = build.project.gl_project
+            = link_to namespace_project_build_path(gl_project.namespace, gl_project, build) do
+              = build.id
+
           %td.status
             = ci_status_with_icon(build.status)
 
@@ -110,8 +116,8 @@
             = build.project.name
 
           %td.build-link
-            = link_to ci_project_build_path(build.project, build) do
-              %strong #{build.short_sha}
+            = link_to ci_status_path(build.commit) do
+              %strong #{build.commit.short_sha}
 
           %td.timestamp
             - if build.finished_at
diff --git a/app/views/ci/builds/_build.html.haml b/app/views/ci/builds/_build.html.haml
deleted file mode 100644
index 8ccc0dff2fbf49ae110a42f250ae3d2530ad13cb..0000000000000000000000000000000000000000
--- a/app/views/ci/builds/_build.html.haml
+++ /dev/null
@@ -1,49 +0,0 @@
-%tr.build
-  %td.status
-    = ci_status_with_icon(build.status)
-
-  %td.build-link
-    = link_to ci_project_build_path(build.project, build) do
-      %strong Build ##{build.id}
-
-  - if defined?(ref)
-    %td
-      = build.ref
-
-  %td
-    = build.stage
-
-  %td
-    = build.name
-    .pull-right
-      - if build.tags.any?
-        - build.tag_list.each do |tag|
-          %span.label.label-primary
-            = tag
-      - if build.trigger_request
-        %span.label.label-info triggered
-      - if build.allow_failure
-        %span.label.label-danger allowed to fail
-
-  %td.duration
-    - if build.duration
-      #{duration_in_words(build.finished_at, build.started_at)}
-
-  %td.timestamp
-    - if build.finished_at
-      %span #{time_ago_in_words build.finished_at} ago
-
-  - if build.project.coverage_enabled?
-    %td.coverage
-      - if build.coverage
-        #{build.coverage}%
-
-  %td
-    - if defined?(controls) && current_user && can?(current_user, :manage_builds, gl_project)
-      .pull-right
-        - if build.active?
-          = link_to cancel_ci_project_build_path(build.project, build, return_to: request.original_url), title: 'Cancel build' do
-            %i.fa.fa-remove.cred
-        - elsif build.commands.present?
-          = link_to retry_ci_project_build_path(build.project, build, return_to: request.original_url), method: :post, title: 'Retry build' do
-            %i.fa.fa-repeat
diff --git a/app/views/ci/builds/show.html.haml b/app/views/ci/builds/show.html.haml
deleted file mode 100644
index c42d11bf05deaa85d25ca212126f5815ef0f84e8..0000000000000000000000000000000000000000
--- a/app/views/ci/builds/show.html.haml
+++ /dev/null
@@ -1,165 +0,0 @@
-#up-build-trace
-- if @commit.matrix_for_ref?(@build.ref)
-  %ul.center-top-menu
-    - @commit.builds_without_retry_for_ref(build.ref).each do |build|
-      %li{class: ('active' if build == @build) }
-        = link_to ci_project_build_url(@project, build) do
-          = ci_icon_for_status(build.status)
-          %span
-            - if build.name
-              = build.name
-            - else
-              = build.id
-
-
-    - unless @commit.builds_without_retry_for_ref(@build.ref).include?(@build)
-      %li.active
-        %a
-          Build ##{@build.id}
-          &middot;
-          %i.fa.fa-warning-sign
-          This build was retried.
-
-.gray-content-block
-  .build-head
-    %h4
-      - if @build.commit.tag?
-        Build for tag
-        %code #{@build.ref}
-      - else
-        Build for commit
-        %strong.monospace= commit_link(@build.commit)
-        from
-
-        = link_to ci_project_path(@build.project, ref: @build.ref) do
-          %strong.monospace= "#{@build.ref}"
-
-      - if @build.duration
-        .pull-right
-          %span
-            %i.fa.fa-time
-            #{duration_in_words(@build.finished_at, @build.started_at)}
-
-    .clearfix
-      = ci_status_with_icon(@build.status)
-      .pull-right
-        = @build.updated_at.stamp('19:00 Aug 27')
-
-.row.prepend-top-default
-  .col-md-9
-    .clearfix
-      - if @build.active?
-        .autoscroll-container
-          %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll
-        .clearfix
-    .scroll-controls
-      = link_to '#up-build-trace', class: 'btn' do
-        %i.fa.fa-angle-up
-      = link_to '#down-build-trace', class: 'btn' do
-        %i.fa.fa-angle-down
-
-    %pre.trace#build-trace
-      %code.bash
-        = preserve do
-          = raw @build.trace_html
-    %div#down-build-trace
-
-  .col-md-3
-    - if @build.coverage
-      .build-widget
-        %h4.title
-          Test coverage
-        %h1 #{@build.coverage}%
-
-
-    .build-widget
-      %h4.title
-        Build
-        - if current_user && can?(current_user, :manage_builds, gl_project)
-          .pull-right
-            - if @build.active?
-              = link_to "Cancel", cancel_ci_project_build_path(@project, @build), class: 'btn btn-sm btn-danger'
-            - elsif @build.commands.present?
-              = link_to "Retry", retry_ci_project_build_path(@project, @build), class: 'btn btn-sm btn-primary', method: :post
-
-      - if @build.duration
-        %p
-          %span.attr-name Duration:
-          #{duration_in_words(@build.finished_at, @build.started_at)}
-      %p
-        %span.attr-name Created:
-        #{time_ago_in_words(@build.created_at)} ago
-      - if @build.finished_at
-        %p
-          %span.attr-name Finished:
-          #{time_ago_in_words(@build.finished_at)} ago
-      %p
-        %span.attr-name Runner:
-        - if @build.runner && current_user && current_user.admin
-          \#{link_to "##{@build.runner.id}", ci_admin_runner_path(@build.runner.id)}
-        - elsif @build.runner
-          \##{@build.runner.id}
-
-    - if @build.trigger_request
-      .build-widget
-        %h4.title
-          Trigger
-
-        %p
-          %span.attr-name Token:
-          #{@build.trigger_request.trigger.short_token}
-
-        - if @build.trigger_request.variables
-          %p
-            %span.attr-name Variables:
-
-          %code
-            - @build.trigger_request.variables.each do |key, value|
-              #{key}=#{value}
-
-    .build-widget
-      %h4.title
-        Commit
-        .pull-right
-          %small #{build_commit_link @build}
-      %p
-        %span.attr-name Branch:
-        #{build_ref_link @build}
-      %p
-        %span.attr-name Author:
-        #{@build.commit.git_author_name}
-      %p
-        %span.attr-name Message:
-        #{@build.commit.git_commit_message}
-
-    - if @build.tags.any?
-      .build-widget
-        %h4.title
-          Tags
-        - @build.tag_list.each do |tag|
-          %span.label.label-primary
-            = tag
-
-    - if @builds.present?
-      .build-widget
-        %h4.title #{pluralize(@builds.count, "other build")} for #{@build.short_sha}:
-        %table.builds
-          - @builds.each_with_index do |build, i|
-            %tr.build
-              %td
-                = ci_icon_for_status(build.status)
-              %td
-                = link_to ci_project_build_url(@project, build) do
-                  - if build.name
-                    = build.name
-                  - else
-                    %span ##{build.id}
-
-              %td.status= build.status
-
-
-        = paginate @builds
-
-
-:javascript
-  new CiBuild("#{ci_project_build_url(@project, @build)}", "#{@build.status}")
diff --git a/app/views/ci/commits/_commit.html.haml b/app/views/ci/commits/_commit.html.haml
index f8a1fa508517c35dec3896f31030d2a0e9e2180c..b24a3b826cfb52a0a8a36144d45ccf5d31111763 100644
--- a/app/views/ci/commits/_commit.html.haml
+++ b/app/views/ci/commits/_commit.html.haml
@@ -7,7 +7,7 @@
 
 
   %td.build-link
-    = link_to ci_project_commits_path(commit.project, commit.sha) do
+    = link_to ci_status_path(commit) do
       %strong #{commit.short_sha}
 
   %td.build-message
@@ -16,7 +16,8 @@
   %td.build-branch
     - unless @ref
       %span
-        = link_to truncate(commit.last_ref, length: 25), ci_project_path(@project, ref: commit.last_ref)
+        - commit.refs.each do |ref|
+          = link_to truncate(ref, length: 25), ci_project_path(@project, ref: ref)
 
   %td.duration
     - if commit.duration > 0
diff --git a/app/views/ci/commits/show.html.haml b/app/views/ci/commits/show.html.haml
deleted file mode 100644
index 7217671fe95351b33cef489d2d58e13644c7113a..0000000000000000000000000000000000000000
--- a/app/views/ci/commits/show.html.haml
+++ /dev/null
@@ -1,81 +0,0 @@
-.commit-info
-  .append-bottom-20
-    = ci_status_with_icon(@commit.status)
-
-  .gray-content-block.middle-block
-    %pre.commit-message
-      #{@commit.git_commit_message}
-
-  .gray-content-block.second-block
-    .row
-      .col-sm-6
-      %p
-        %span.attr-name Commit:
-        #{gitlab_commit_link(@project, @commit.sha)}
-      .col-sm-6
-        - if @commit.git_author_name || @commit.git_author_email
-          %p
-            %span.attr-name Author:
-            #{@commit.git_author_name} (#{@commit.git_author_email})
-        - if @commit.created_at
-          %p
-            %span.attr-name Created at:
-            #{@commit.created_at.to_s(:short)}
-
-- if current_user && can?(current_user, :manage_builds, gl_project)
-  .pull-right
-    - if @commit.builds.running_or_pending.any?
-      = link_to "Cancel", cancel_ci_project_commits_path(@project, @commit), class: 'btn btn-sm btn-danger'
-
-
-- if @commit.yaml_errors.present?
-  .bs-callout.bs-callout-danger
-    %h4 Found errors in your .gitlab-ci.yml:
-    %ul
-      - @commit.yaml_errors.split(",").each do |error|
-        %li= error
-
-- unless @commit.ci_yaml_file
-  .bs-callout.bs-callout-warning
-    \.gitlab-ci.yml not found in this commit
-
-- @commit.refs.each do |ref|
-  %h3
-    Builds for #{ref}
-    - if @commit.duration_for_ref(ref) > 0
-      %small.pull-right
-        %i.fa.fa-time
-        #{time_interval_in_words @commit.duration_for_ref(ref)}
-
-  %table.table.builds
-    %thead
-      %tr
-        %th Status
-        %th Build ID
-        %th Stage
-        %th Name
-        %th Duration
-        %th Finished at
-        - if @project.coverage_enabled?
-          %th Coverage
-        %th
-    = render @commit.builds_without_retry.for_ref(ref), controls: true
-
-- if @commit.retried_builds.any?
-  %h3
-    Retried builds
-
-  %table.table.builds
-    %thead
-      %tr
-        %th Status
-        %th Build ID
-        %th Ref
-        %th Stage
-        %th Name
-        %th Duration
-        %th Finished at
-        - if @project.coverage_enabled?
-          %th Coverage
-        %th
-    = render @commit.retried_builds, ref: true
diff --git a/app/views/ci/notify/build_fail_email.html.haml b/app/views/ci/notify/build_fail_email.html.haml
index 4ebdfa1b6c088d884f62efef3dcc7422facb4478..69689a75022fcb6146f40d45ec0d773de49aa207 100644
--- a/app/views/ci/notify/build_fail_email.html.haml
+++ b/app/views/ci/notify/build_fail_email.html.haml
@@ -16,4 +16,4 @@
   Message: #{@build.commit.git_commit_message}
 
 %p
-  Url: #{link_to @build.short_sha, ci_project_build_url(@project, @build)}
+  Url: #{link_to @build.short_sha, namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build)}
diff --git a/app/views/ci/notify/build_fail_email.text.erb b/app/views/ci/notify/build_fail_email.text.erb
index 177827f9a3c1c2aa16874f6a840c598aa6c1a685..6de5dc10f179184ffdbf0591ff0380a42739ae0e 100644
--- a/app/views/ci/notify/build_fail_email.text.erb
+++ b/app/views/ci/notify/build_fail_email.text.erb
@@ -6,4 +6,4 @@ Author:   <%= @build.commit.git_author_name %>
 Branch:   <%= @build.ref %>
 Message:  <%= @build.commit.git_commit_message %>
 
-Url:      <%= ci_project_build_url(@build.project, @build) %>
+Url:      <%= namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build) %>
diff --git a/app/views/ci/notify/build_success_email.html.haml b/app/views/ci/notify/build_success_email.html.haml
index 7cc43300e883e4a45986a526db88af6b9c1a6922..4e3015a356bea801bea8087a7fe051445167b8be 100644
--- a/app/views/ci/notify/build_success_email.html.haml
+++ b/app/views/ci/notify/build_success_email.html.haml
@@ -17,4 +17,4 @@
   Message: #{@build.commit.git_commit_message}
 
 %p
-  Url: #{link_to @build.short_sha, ci_project_build_url(@project, @build)}
+  Url: #{link_to @build.short_sha, namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build)}
diff --git a/app/views/ci/notify/build_success_email.text.erb b/app/views/ci/notify/build_success_email.text.erb
index 4d55c39b0fb7c6e5e5c3481949cf85de57125ec0..d0a43ae1c12915fd47fd85b6d0b14eb25a9b1c70 100644
--- a/app/views/ci/notify/build_success_email.text.erb
+++ b/app/views/ci/notify/build_success_email.text.erb
@@ -6,4 +6,4 @@ Author:   <%= @build.commit.git_author_name %>
 Branch:   <%= @build.ref %>
 Message:  <%= @build.commit.git_commit_message %>
 
-Url:      <%= ci_project_build_url(@build.project, @build) %>
+Url:      <%= namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build) %>
diff --git a/app/views/ci/projects/_info.html.haml b/app/views/ci/projects/_info.html.haml
deleted file mode 100644
index 1888e1bde93166b9a800869243fadf53a1e857ae..0000000000000000000000000000000000000000
--- a/app/views/ci/projects/_info.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-- if no_runners_for_project?(@project)
-  = render 'no_runners'
diff --git a/app/views/ci/projects/show.html.haml b/app/views/ci/projects/show.html.haml
deleted file mode 100644
index 888b1ea41d546c445ba394592d07915cbe8ce876..0000000000000000000000000000000000000000
--- a/app/views/ci/projects/show.html.haml
+++ /dev/null
@@ -1,60 +0,0 @@
-= render 'ci/shared/guide' unless @project.setup_finished?
-
-- if current_user && can?(current_user, :manage_project, gl_project) && !@project.any_runners?
-  .alert.alert-danger
-    Builds for this project wont be served unless you configure runners on
-    = link_to "Runners page", runners_path(@project.gl_project)
-
-%ul.nav.nav-tabs.append-bottom-20
-  %li{class: ref_tab_class}
-    = link_to 'All commits', ci_project_path(@project)
-  - @project.tracked_refs.each do |ref|
-    %li{class: ref_tab_class(ref)}
-      = link_to ref, ci_project_path(@project, ref: ref)
-
-  - if @ref && !@project.tracked_refs.include?(@ref)
-    %li{class: 'active'}
-      = link_to @ref, ci_project_path(@project, ref: @ref)
-
-  %li.pull-right
-    = link_to 'Go to project', project_path(gl_project), class: 'btn btn-sm'
-
-- if @ref
-  %p
-    Paste build status image for #{@ref} with next link
-    = link_to '#', class: 'badge-codes-toggle btn btn-default btn-xs' do
-      Status Badge
-    .badge-codes-block.bs-callout.bs-callout-info.hide
-      %p
-        Status badge for
-        %span.label.label-info #{@ref}
-        branch
-      %div
-        %label Markdown:
-        = text_field_tag 'badge_md', markdown_badge_code(@project, @ref), readonly: true, class: 'form-control'
-        %label Html:
-        = text_field_tag 'badge_html', html_badge_code(@project, @ref), readonly: true, class: 'form-control'
-
-
-
-
-%table.table.builds
-  %thead
-    %tr
-      %th Status
-      %th Commit
-      %th Message
-      %th Branch
-      %th Total duration
-      %th Finished at
-      - if @project.coverage_enabled?
-        %th Coverage
-
-  = render @commits
-
-= paginate @commits
-
-- if @commits.empty?
-  .bs-callout
-    %h4 No commits yet
-
diff --git a/app/views/dashboard/_activities.html.haml b/app/views/dashboard/_activities.html.haml
index 19d919f9b6a99a456d12452899d0a3ada744d448..f98fd9f06ba707c49ae8325da944e1a54198c500 100644
--- a/app/views/dashboard/_activities.html.haml
+++ b/app/views/dashboard/_activities.html.haml
@@ -3,10 +3,9 @@
 
 .gray-content-block
   - if current_user
-    %ul.nav.nav-pills.event_filter.pull-right
-      %li.pull-right
-        = link_to dashboard_projects_path(:atom, { private_token: current_user.private_token }), class: 'rss-btn' do
-          %i.fa.fa-rss
+    .pull-right
+      = link_to dashboard_projects_path(:atom, { private_token: current_user.private_token }), class: 'btn rss-btn' do
+        %i.fa.fa-rss
   = render 'shared/event_filter'
 
 .content_list
diff --git a/app/views/dashboard/projects/_projects.html.haml b/app/views/dashboard/projects/_projects.html.haml
index e09e032a7f1c92111c2614b06051428c10059a24..81a5909e2d2ac5f01430f000bf0512306320cedd 100644
--- a/app/views/dashboard/projects/_projects.html.haml
+++ b/app/views/dashboard/projects/_projects.html.haml
@@ -1,10 +1,11 @@
 .projects-list-holder
   .projects-search-form
     .input-group
-      = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control'
+      = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
       - if current_user.can_create_project?
         %span.input-group-btn
           = link_to new_project_path, class: 'btn btn-green' do
-            New project
+            %i.fa.fa-plus
+            New Project
 
   = render 'shared/projects/list', projects: @projects, ci: true
diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml
index 83d4d321c8311bdd0fac3ba20524f27cb7de5da9..fcb07b04083ae03470f5f608e267b66a74426484 100644
--- a/app/views/explore/groups/index.html.haml
+++ b/app/views/explore/groups/index.html.haml
@@ -11,7 +11,7 @@
     = form_tag explore_groups_path, method: :get, class: 'form-inline form-tiny' do |f|
       = hidden_field_tag :sort, @sort
       .form-group
-        = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "groups_search"
+        = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "groups_search", spellcheck: false
       .form-group
         = button_tag 'Search', class: "btn btn-default"
 
diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml
index 5a3d689d1e5ce42887a7639b38d2ef4b4d411605..2761272aa8ab15d40a2d575da4f2da92bbf391e6 100644
--- a/app/views/explore/projects/_filter.html.haml
+++ b/app/views/explore/projects/_filter.html.haml
@@ -1,7 +1,7 @@
 .pull-left
   = form_tag explore_projects_filter_path, method: :get, class: 'form-inline form-tiny' do |f|
     .form-group
-      = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search"
+      = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search", spellcheck: false
     .form-group
       = button_tag 'Search', class: "btn btn-success"
 
diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml
index 2b27a88794d31966b8277f370ea6b203d1dbe1bc..11d69977ef9e03b87fd2c5bb113cd131651fb1d7 100644
--- a/app/views/groups/_projects.html.haml
+++ b/app/views/groups/_projects.html.haml
@@ -1,10 +1,11 @@
 .panel.panel-default.projects-list-holder
   .panel-heading.clearfix
     .input-group
-      = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control'
+      = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
       - if can? current_user, :create_projects, @group
         %span.input-group-btn
           = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-green' do
-            New project
+            %i.fa.fa-plus
+            New Project
 
-  = render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false
+  = render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 3a6d07ebddf956a3ea051334396d458e8a898d9a..fee4b0052b590af4f5c3f62d65717275c7e120eb 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -12,7 +12,7 @@
 .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' }
+      = 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'
 
   - if current_user && current_user.can?(:admin_group_member, @group)
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index a9ba9d2ba101a31bf1ad716ec1586d314aa8281a..dc8e81323a63daf43f7e527162142042b3a37111 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -25,11 +25,9 @@
         .hidden-xs
           - if current_user
             = render "events/event_last_push", event: @last_push
-
-            %ul.nav.nav-pills.event_filter.pull-right
-              %li
-                = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'rss-btn' do
-                  %i.fa.fa-rss
+            .pull-right
+              = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'btn rss-btn' do
+                %i.fa.fa-rss
 
             = render 'shared/event_filter'
             %hr
diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml
index 7c89457ace3885129eaea47487e560ead6dec74a..2169a821fb24c6fc22c7c6a01224430d82726610 100644
--- a/app/views/help/ui.html.haml
+++ b/app/views/help/ui.html.haml
@@ -14,6 +14,8 @@
       = link_to 'Lists', '#lists'
     %li
       = link_to 'Tables', '#tables'
+    %li
+      = link_to 'Nav', '#nav'
     %li
       = link_to 'Buttons', '#buttons'
     %li
@@ -30,16 +32,31 @@
   %h2#blocks Blocks
 
   %h3
-    %code .well
+    %code .gray-content-block
+
 
 
-  .well
-    %h4 Something
+  .gray-content-block.middle-block
+    %h4 Normal block inside content
+    = lorem
+
+  .gray-content-block.second-block
+    %h4 Second block
     = lorem
 
 
   %h2#lists Lists
 
+  %h3
+    %code .content-list
+  %ul.content-list
+    %li
+      One item
+    %li
+      One item
+    %li
+      One item
+
   %h3
     %code .well-list
   %ul.well-list
@@ -102,11 +119,40 @@
           %td the Bird
           %td @twitter
 
+  %h2#navs Navigation
+
+  %h3
+    %code .center-top-menu
+  .example
+    %ul.center-top-menu
+      %li.active
+        %a Open
+      %li
+        %a Closed
+
+  %h3
+    %code .btn-group.btn-group-next
+  .example
+    %div.btn-group.btn-group-next
+      %a.btn.active Open
+      %a.btn Closed
+
+
+  %h3
+    %code .nav.nav-tabs
+  .example
+    %ul.nav.nav-tabs
+      %li.active
+        %a Open
+      %li
+        %a Closed
+
 
   %h2#buttons Buttons
 
   .example
     %button.btn.btn-default{:type => "button"} Default
+    %button.btn.btn-gray{:type => "button"} Gray
     %button.btn.btn-primary{:type => "button"} Primary
     %button.btn.btn-success{:type => "button"} Success
     %button.btn.btn-info{:type => "button"} Info
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 2468687b56d8c26894e9bc91b749b0b3a3a30f6d..1a883e20e899dea4f3dd4b7e7b3536b137ef6741 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -6,7 +6,7 @@
         = brand_header_logo
         .gitlab-text-container
           %h3 GitLab
-          
+
     - if defined?(sidebar) && sidebar
       = render "layouts/nav/#{sidebar}"
     - elsif current_user
@@ -23,6 +23,7 @@
           = current_user.username
   .content-wrapper
     = render "layouts/flash"
+    = yield :flash_message
     %div{ class: container_class }
       .content
         .clearfix
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index e2d2dec7ab814d3d98df01734db0e8bb998e9dd8..ceb64ce3157f69fd054ece96b2fcfac9f66ea4fc 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -1,6 +1,6 @@
 .search
   = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f|
-    = search_field_tag "search", nil, placeholder: search_placeholder, class: "search-input form-control"
+    = search_field_tag "search", nil, placeholder: search_placeholder, class: "search-input form-control", spellcheck: false
     = hidden_field_tag :group_id, @group.try(:id)
     - if @project && @project.persisted?
       = hidden_field_tag :project_id, @project.id
diff --git a/app/views/layouts/ci/_nav_project.html.haml b/app/views/layouts/ci/_nav_project.html.haml
index 545abc23d995d8d58edec445b6a2df5a5af1640b..f094edbfa87cac6accd2c5e2380a45225f5176fe 100644
--- a/app/views/layouts/ci/_nav_project.html.haml
+++ b/app/views/layouts/ci/_nav_project.html.haml
@@ -5,17 +5,6 @@
       %span
         Back to project
   %li.separate-item
-  = nav_link path: ['projects#show', 'commits#show', 'builds#show'] do
-    = link_to ci_project_path(@project) do
-      = icon('list-alt fw')
-      %span
-        Commits
-        %span.count= @project.commits.count
-    = nav_link path: ['services#index', 'services#edit'] do
-      = link_to ci_project_services_path(@project) do
-        = icon('share fw')
-        %span
-          Services
     = nav_link path: 'events#index' do
       = link_to ci_project_events_path(@project) do
         = icon('book fw')
diff --git a/app/views/layouts/ci/build.html.haml b/app/views/layouts/ci/build.html.haml
deleted file mode 100644
index a1356f0dc2ea2b802c5c7be62e681769951dba82..0000000000000000000000000000000000000000
--- a/app/views/layouts/ci/build.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-!!! 5
-%html{ lang: "en"}
-  = render 'layouts/head'
-  %body{class: "ci-body #{user_application_theme}", 'data-page' => body_data_page}
-    - header_title ci_commit_title(@commit)
-    - if current_user
-      = render "layouts/header/default", title: header_title
-    - else
-      = render "layouts/header/public", title: header_title
-
-    = render 'layouts/ci/page', sidebar: 'nav_project'
diff --git a/app/views/layouts/ci/commit.html.haml b/app/views/layouts/ci/commit.html.haml
deleted file mode 100644
index a1356f0dc2ea2b802c5c7be62e681769951dba82..0000000000000000000000000000000000000000
--- a/app/views/layouts/ci/commit.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-!!! 5
-%html{ lang: "en"}
-  = render 'layouts/head'
-  %body{class: "ci-body #{user_application_theme}", 'data-page' => body_data_page}
-    - header_title ci_commit_title(@commit)
-    - if current_user
-      = render "layouts/header/default", title: header_title
-    - else
-      = render "layouts/header/public", title: header_title
-
-    = render 'layouts/ci/page', sidebar: 'nav_project'
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index a218ec7486cf9fe649e08ec4c92bfa3bcd1e7220..e4c285d802380d51b46445843c91a8843ed58e91 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -32,7 +32,7 @@
           Files
 
   - if project_nav_tab? :commits
-    = nav_link(controller: %w(commit commits compare repositories tags branches)) do
+    = nav_link(controller: %w(commit commits compare repositories tags branches builds)) do
       = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do
         = icon('history fw')
         %span
@@ -76,13 +76,6 @@
           Merge Requests
           %span.count.merge_counter= @project.merge_requests.opened.count
 
-  - if @project.gitlab_ci?
-    = nav_link(controller: [:ci, :project]) do
-      = link_to ci_project_path(@project.gitlab_ci_project), title: 'Continuous Integration', data: {placement: 'right'} do
-        = icon('building fw')
-        %span
-          Continuous Integration
-
   - if project_nav_tab? :settings
     = nav_link(controller: [:project_members, :teams]) do
       = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab', data: {placement: 'right'} do
diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml
index 9279a846623a088b3711099356747bb6c8a9f38c..954dbe5d2b9079c39f6fd76c1ee8bf8545e9c6b0 100644
--- a/app/views/layouts/nav/_project_settings.html.haml
+++ b/app/views/layouts/nav/_project_settings.html.haml
@@ -60,3 +60,13 @@
           = icon('building fw')
           %span
             CI Settings
+      = nav_link controller: 'ci_services' do
+        = link_to namespace_project_ci_services_path(@project.namespace, @project) do
+          = icon('share fw')
+          %span
+            CI Services
+      = nav_link path: 'events#index' do
+        = link_to ci_project_events_path(@project.gitlab_ci_project) do
+          = icon('book fw')
+          %span
+            CI Events
diff --git a/app/views/profiles/keys/_key_details.html.haml b/app/views/profiles/keys/_key_details.html.haml
index e0ae4d9720fdb54a2aa110ba58427b5212c8c9b5..0ca8bd95157a3f12d1238d1cf34f24a769735d7b 100644
--- a/app/views/profiles/keys/_key_details.html.haml
+++ b/app/views/profiles/keys/_key_details.html.haml
@@ -18,5 +18,6 @@
       %code.key-fingerprint= @key.fingerprint
     %pre.well-pre
       = @key.key
-  .pull-right
-    = link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
+  .col-md-12
+    .pull-right
+      = link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml
index 1261f6254d7a016b69ef1bc447245c4ef2a1c0f9..c2683bc62194754b8818c46d9839c7da6ff71b01 100644
--- a/app/views/projects/_activity.html.haml
+++ b/app/views/projects/_activity.html.haml
@@ -1,10 +1,9 @@
 = render 'projects/last_push'
 .gray-content-block.activity-filter-block
   - if current_user
-    %ul.nav.nav-pills.event_filter.pull-right
-      %li
-        = link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "Feed", class: 'rss-btn' do
-          %i.fa.fa-rss
+    .pull-right
+      = link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "Feed", class: 'btn rss-btn' do
+        %i.fa.fa-rss
 
   = render 'shared/event_filter'
 .content_list{:"data-href" => activity_project_path(@project)}
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index b4c7d8b9b71112435caefe74b49a388c3a5c9628..a1ae1397584ea63494c8f788c02d32181c88114a 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -19,7 +19,7 @@
   - blob_commit = @repository.last_commit_for_path(@commit.id, blob.path)
   = render blob_commit, project: @project
 
-%div#tree-content-holder.tree-content-holder
+%div#blob-content-holder.blob-content-holder
   %article.file-holder
     .file-title
       = blob_icon blob.mode, blob.name
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 9c3e1703c893148dc66df5cf6e31ccaa684104c8..f1ad0c3c403ca45338dcace3d94e2fe0dfda7230 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -11,7 +11,7 @@
       - if current_action?(:new) || current_action?(:create)
         \/
         = text_field_tag 'file_name', params[:file_name], placeholder: "File name",
-          required: true, class: 'form-control new-file-name'
+          required: true, class: 'form-control new-file-name js-quick-submit'
       .pull-right
         = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'form-control'
 
diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..cb1567a2e68b527a5235f30328f5ceea65e13496
--- /dev/null
+++ b/app/views/projects/blob/_new_dir.html.haml
@@ -0,0 +1,25 @@
+#modal-create-new-dir.modal
+  .modal-dialog
+    .modal-content
+      .modal-header
+        %a.close{href: "#", "data-dismiss" => "modal"} ×
+        %h3.page-title Create New Directory
+      .modal-body
+        = form_tag namespace_project_create_dir_path(@project.namespace, @project, @id), method: :post, remote: false, id: 'dir-create-form', class: 'form-horizontal' do
+          .form-group
+            = label_tag :dir_name, 'Directory Name', class: 'control-label'
+            .col-sm-10
+              = text_field_tag :dir_name, params[:dir_name], placeholder: "Directory name", required: true, class: 'form-control'
+          = render 'shared/commit_message_container', params: params, placeholder: ''
+          - unless @project.empty_repo?
+            .form-group
+              = label_tag :branch_name, 'Branch', class: 'control-label'
+              .col-sm-10
+                = text_field_tag 'new_branch', @ref, class: "form-control"
+          .form-group
+            .col-sm-offset-2.col-sm-10
+              = submit_tag "Create directory", class: 'btn btn-primary btn-create'
+              = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
+
+:coffeescript
+  disableButtonIfAnyEmptyField($("#dir-create-form"), ".form-control", ".btn-create");
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
index 1a1df12770324e7408e9509c09b8a685f143e3c8..e27f17075273670bae618d1498232fff394678ad 100644
--- a/app/views/projects/blob/_upload.html.haml
+++ b/app/views/projects/blob/_upload.html.haml
@@ -4,9 +4,6 @@
       .modal-header
         %a.close{href: "#", "data-dismiss" => "modal"} ×
         %h3.page-title #{title}
-        %p.light
-          From branch
-          %strong= @ref
       .modal-body
         = form_tag form_path, method: method, class: 'blob-file-upload-form-js form-horizontal' do
           .dropzone
@@ -18,6 +15,12 @@
           .dropzone-alerts{class: "alert alert-danger data", style: "display:none"}
           = render 'shared/commit_message_container', params: params,
             placeholder: placeholder
+          - unless @project.empty_repo?
+            .form-group.branch
+              = label_tag 'branch', class: 'control-label' do
+                Branch
+              .col-sm-10
+                = text_field_tag 'new_branch', @ref, class: "form-control"
           .form-group
             .col-sm-offset-2.col-sm-10
               = button_tag button_title, class: 'btn btn-small btn-primary btn-upload-file', id: 'submit-all'
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index 1950586b11280357e6a29df530ef74a1fecebc16..7975137c37f018f20911f5c9370c474cd3deb303 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -2,12 +2,7 @@
 = render "header_title"
 
 .gray-content-block.top-block
-  Create a new file or
-  = link_to 'upload', '#modal-upload-blob',
-    { class: 'upload-link', 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'}
-  an existing one
-
-= render 'projects/blob/upload', title: 'Upload', placeholder: 'Upload new file', button_title: 'Upload file', form_path: namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post
+  Create a new file
 
 .file-editor
   = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal form-new-file js-requires-input') do
@@ -20,7 +15,7 @@
         = label_tag 'branch', class: 'control-label' do
           Branch
         .col-sm-10
-          = text_field_tag 'new_branch', @ref, class: "form-control"
+          = text_field_tag 'new_branch', @ref, class: "form-control js-quick-submit"
 
     = hidden_field_tag 'content', '', id: 'file-content'
     = render 'projects/commit_button', ref: @ref,
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..91c1b16c9f69064df91e71739628440cae1ec31b
--- /dev/null
+++ b/app/views/projects/builds/show.html.haml
@@ -0,0 +1,180 @@
+.build-page
+  .gray-content-block
+    Build for commit
+    %strong.monospace
+      = link_to @build.commit.short_sha, ci_status_path(@build.commit)
+    from
+    %code #{@build.ref}
+
+  #up-build-trace
+  - if @commit.matrix_for_ref?(@build.ref)
+    %ul.center-top-menu.build-top-menu
+      - @commit.latest_builds_for_ref(@build.ref).each do |build|
+        %li{class: ('active' if build == @build) }
+          = link_to namespace_project_build_path(@project.namespace, @project, build) do
+            = ci_icon_for_status(build.status)
+            %span
+              - if build.name
+                = build.name
+              - else
+                = build.id
+
+
+      - unless @commit.latest_builds_for_ref(@build.ref).include?(@build)
+        %li.active
+          %a
+            Build ##{@build.id}
+            &middot;
+            %i.fa.fa-warning
+            This build was retried.
+
+  .gray-content-block.second-block
+    .build-head
+      .clearfix
+        = ci_status_with_icon(@build.status)
+        - if @build.duration
+          %span
+            %i.fa.fa-time
+            #{duration_in_words(@build.finished_at, @build.started_at)}
+        .pull-right
+          = @build.updated_at.stamp('19:00 Aug 27')
+
+  - if @build.show_warning?
+    - unless @build.any_runners_online?
+      .bs-callout.bs-callout-warning
+        %p
+          - if no_runners_for_project?(@build.project)
+            This build is stuck, because the project doesn't have runners assigned.
+          - elsif @build.tags.any?
+            This build is stuck.
+            %br
+            This build is stuck, because you don't have any active runners online with these tags assigned to the project:
+            - @build.tags.each do |tag|
+              %span.label.label-primary
+                = tag
+          - else
+            This build is stuck, because you don't have any active runners online that can run this build.
+
+          %br
+          Go to
+          = link_to namespace_project_runners_path(@build.gl_project.namespace, @build.gl_project) do
+            Runners page
+
+  .row.prepend-top-default
+    .col-md-9
+      .clearfix
+        - if @build.active?
+          .autoscroll-container
+            %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll
+          .clearfix
+      .scroll-controls
+        = link_to '#up-build-trace', class: 'btn' do
+          %i.fa.fa-angle-up
+        = link_to '#down-build-trace', class: 'btn' do
+          %i.fa.fa-angle-down
+
+      %pre.trace#build-trace
+        %code.bash
+          = preserve do
+            = raw @build.trace_html
+      %div#down-build-trace
+
+    .col-md-3
+      - if @build.coverage
+        .build-widget
+          %h4.title
+            Test coverage
+          %h1 #{@build.coverage}%
+
+
+      .build-widget
+        %h4.title
+          Build
+          - if current_user && can?(current_user, :manage_builds, @project)
+            .pull-right
+              - if @build.active?
+                = link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-danger'
+              - elsif @build.commands.present?
+                = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-primary', method: :post
+
+        - if @build.duration
+          %p
+            %span.attr-name Duration:
+            #{duration_in_words(@build.finished_at, @build.started_at)}
+        %p
+          %span.attr-name Created:
+          #{time_ago_in_words(@build.created_at)} ago
+        - if @build.finished_at
+          %p
+            %span.attr-name Finished:
+            #{time_ago_in_words(@build.finished_at)} ago
+        %p
+          %span.attr-name Runner:
+          - if @build.runner && current_user && current_user.admin
+            \#{link_to "##{@build.runner.id}", ci_admin_runner_path(@build.runner.id)}
+          - elsif @build.runner
+            \##{@build.runner.id}
+
+      - if @build.trigger_request
+        .build-widget
+          %h4.title
+            Trigger
+
+          %p
+            %span.attr-name Token:
+            #{@build.trigger_request.trigger.short_token}
+
+          - if @build.trigger_request.variables
+            %p
+              %span.attr-name Variables:
+
+            %code
+              - @build.trigger_request.variables.each do |key, value|
+                #{key}=#{value}
+
+      .build-widget
+        %h4.title
+          Commit
+          .pull-right
+            %small #{build_commit_link @build}
+        %p
+          %span.attr-name Branch:
+          #{build_ref_link @build}
+        %p
+          %span.attr-name Author:
+          #{@build.commit.git_author_name}
+        %p
+          %span.attr-name Message:
+          #{@build.commit.git_commit_message}
+
+      - if @build.tags.any?
+        .build-widget
+          %h4.title
+            Tags
+          - @build.tag_list.each do |tag|
+            %span.label.label-primary
+              = tag
+
+      - if @builds.present?
+        .build-widget
+          %h4.title #{pluralize(@builds.count, "other build")} for #{@build.short_sha}:
+          %table.table.builds
+            - @builds.each_with_index do |build, i|
+              %tr.build
+                %td
+                  = ci_icon_for_status(build.status)
+                %td
+                  = link_to namespace_project_build_path(@project.namespace, @project, @build) do
+                    - if build.name
+                      = build.name
+                    - else
+                      %span ##{build.id}
+
+                %td.status= build.status
+
+
+          = paginate @builds
+
+
+  :javascript
+    new CiBuild("#{namespace_project_build_path(@project.namespace, @project, @build)}", "#{@build.status}")
diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/projects/buttons/_notifications.html.haml
index 4b69a6d7a6f2c478a4b8b2df0ef8bf2d313973d5..3bc2daeec4ed10dee40e8255083bb4c0669e4b78 100644
--- a/app/views/projects/buttons/_notifications.html.haml
+++ b/app/views/projects/buttons/_notifications.html.haml
@@ -1,6 +1,6 @@
 - return unless @membership
 
-= form_tag profile_notifications_path, method: :put, remote: true, class: 'inline-form', id: 'notification-form' do
+= form_tag profile_notifications_path, method: :put, remote: true, class: 'inline', id: 'notification-form' do
   = hidden_field_tag :notification_type, 'project'
   = hidden_field_tag :notification_id, @membership.id
   = hidden_field_tag :notification_level
diff --git a/app/views/ci/services/_form.html.haml b/app/views/projects/ci_services/_form.html.haml
similarity index 80%
rename from app/views/ci/services/_form.html.haml
rename to app/views/projects/ci_services/_form.html.haml
index 9110aaa0528fe3c93da1a3097aaee280e8f181a9..397832e56dbe8f7768578a17cde73f04a3251317 100644
--- a/app/views/ci/services/_form.html.haml
+++ b/app/views/projects/ci_services/_form.html.haml
@@ -4,13 +4,10 @@
 
 %p= @service.description
 
-.back-link
-  = link_to ci_project_services_path(@project) do
-    &larr; to services
 
 %hr
 
-= form_for(@service, as: :service, url: ci_project_service_path(@project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |f|
+= form_for(@service, as: :service, url: namespace_project_ci_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |f|
   - if @service.errors.any?
     .alert.alert-danger
       %ul
@@ -54,4 +51,4 @@
     = f.submit 'Save', class: 'btn btn-save'
     &nbsp;
     - if @service.valid? && @service.activated? && @service.can_test?
-      = link_to 'Test settings', test_ci_project_service_path(@project, @service.to_param), class: 'btn'
+      = link_to 'Test settings', test_namespace_project_ci_service_path(@project.namespace, @project, @service.to_param), class: 'btn'
diff --git a/app/views/ci/services/edit.html.haml b/app/views/projects/ci_services/edit.html.haml
similarity index 100%
rename from app/views/ci/services/edit.html.haml
rename to app/views/projects/ci_services/edit.html.haml
diff --git a/app/views/ci/services/index.html.haml b/app/views/projects/ci_services/index.html.haml
similarity index 81%
rename from app/views/ci/services/index.html.haml
rename to app/views/projects/ci_services/index.html.haml
index 37e5723b54139cd585df24b8eba55618cc12afd7..c78b21884a314c9aa779ca7f7dc788d27ea70c9d 100644
--- a/app/views/ci/services/index.html.haml
+++ b/app/views/projects/ci_services/index.html.haml
@@ -13,7 +13,7 @@
       %td
         = boolean_to_icon service.activated?
       %td
-        = link_to edit_ci_project_service_path(@project, service.to_param) do
+        = link_to edit_namespace_project_ci_service_path(@project.namespace, @project, service.to_param) do
           %strong= service.title
       %td
         = service.description
diff --git a/app/views/projects/ci_settings/_form.html.haml b/app/views/projects/ci_settings/_form.html.haml
index 9f891f557a9d3f1ff4bd1d1c5918eb0933eb2704..d711413c6b956b147c9ddc3a7226e7a84fa6c8e8 100644
--- a/app/views/projects/ci_settings/_form.html.haml
+++ b/app/views/projects/ci_settings/_form.html.haml
@@ -8,6 +8,22 @@
     Edit your
     #{link_to ".gitlab-ci.yml using web-editor", yaml_web_editor_link(@ci_project)}
 
+- unless @project.empty_repo?
+  %p
+    Paste build status image for #{@repository.root_ref} with next link
+    = link_to '#', class: 'badge-codes-toggle btn btn-default btn-xs' do
+      Status Badge
+    .badge-codes-block.bs-callout.bs-callout-info.hide
+      %p
+        Status badge for
+        %span.label.label-info #{@ref}
+        branch
+      %div
+        %label Markdown:
+        = text_field_tag 'badge_md', markdown_badge_code(@ci_project, @repository.root_ref), readonly: true, class: 'form-control'
+        %label Html:
+        = text_field_tag 'badge_html', html_badge_code(@ci_project, @repository.root_ref), readonly: true, class: 'form-control'
+
 = nested_form_for @ci_project, url: namespace_project_ci_settings_path(@project.namespace, @project), html: { class: 'form-horizontal' } do |f|
   - if @ci_project.errors.any?
     #error_explanation
diff --git a/app/views/ci/projects/_no_runners.html.haml b/app/views/projects/ci_settings/_no_runners.html.haml
similarity index 87%
rename from app/views/ci/projects/_no_runners.html.haml
rename to app/views/projects/ci_settings/_no_runners.html.haml
index c0a296fb17d72e8614e9656f2a47be689e809b14..33038c529780ed45aeba6ccbd2a4a2576aa33faf 100644
--- a/app/views/ci/projects/_no_runners.html.haml
+++ b/app/views/projects/ci_settings/_no_runners.html.haml
@@ -4,5 +4,5 @@
     %br
     You can add Specific runner for this project on Runners page
 
-    - if current_user.is_admin
+    - if current_user.admin
       or add Shared runner for whole application in admin are.
diff --git a/app/views/projects/ci_settings/edit.html.haml b/app/views/projects/ci_settings/edit.html.haml
index e9040fe4337621eb81709613b07c72bc917be120..eedf484bf00f2105548175ba9d749e878a76e8d8 100644
--- a/app/views/projects/ci_settings/edit.html.haml
+++ b/app/views/projects/ci_settings/edit.html.haml
@@ -6,6 +6,9 @@
     yaml file which is based on your old jobs.
     Put this file to the root of your project and name it .gitlab-ci.yml
 
+- if no_runners_for_project?(@ci_project)
+  = render 'no_runners'
+
 = render 'form'
 
 - if @ci_project.generated_yaml_config
diff --git a/app/views/projects/commit/_ci_menu.html.haml b/app/views/projects/commit/_ci_menu.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a634ae5dfda5e623178a5d34399e55b7465ce608
--- /dev/null
+++ b/app/views/projects/commit/_ci_menu.html.haml
@@ -0,0 +1,7 @@
+%ul.center-top-menu.commit-ci-menu
+  = nav_link(path: 'commit#show') do
+    = link_to namespace_project_commit_path(@project.namespace, @project, @commit.id) do
+      Changes
+  = nav_link(path: 'commit#ci') do
+    = link_to ci_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
+      Builds
diff --git a/app/views/projects/commit/ci.html.haml b/app/views/projects/commit/ci.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..ca71a91af156d0ececae7c1e06001b7b79953ef7
--- /dev/null
+++ b/app/views/projects/commit/ci.html.haml
@@ -0,0 +1,67 @@
+- page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
+= render "projects/commits/header_title"
+= render "commit_box"
+= render "ci_menu"
+
+
+- if @ci_commit.yaml_errors.present?
+  .bs-callout.bs-callout-danger
+    %h4 Found errors in your .gitlab-ci.yml:
+    %ul
+      - @ci_commit.yaml_errors.split(",").each do |error|
+        %li= error
+
+- unless @ci_commit.ci_yaml_file
+  .bs-callout.bs-callout-warning
+    \.gitlab-ci.yml not found in this commit
+
+.gray-content-block.second-block
+  Latest builds
+
+  .pull-right
+    - if @ci_commit.duration > 0
+      %i.fa.fa-time
+      #{time_interval_in_words @ci_commit.duration}
+
+    &nbsp;
+
+    - if @ci_project && current_user && can?(current_user, :manage_builds, @project)
+      - if @ci_commit.builds.running_or_pending.any?
+        = link_to "Cancel all", cancel_builds_namespace_project_commit_path(@project.namespace, @project, @commit.sha), class: 'btn btn-xs btn-danger'
+
+%table.table.builds
+  %thead
+    %tr
+      %th Status
+      %th Build ID
+      %th Ref
+      %th Stage
+      %th Name
+      %th Duration
+      %th Finished at
+      - if @ci_project && @ci_project.coverage_enabled?
+        %th Coverage
+      %th
+  - @ci_commit.refs.each do |ref|
+    = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest.ordered,
+             locals: { coverage: @ci_project.try(:coverage_enabled?), allow_retry: true }
+
+- if @ci_commit.retried.any?
+  .gray-content-block.second-block
+    Retried builds
+
+  %table.table.builds
+    %thead
+      %tr
+        %th Status
+        %th Build ID
+        %th Ref
+        %th Stage
+        %th Name
+        %th Duration
+        %th Finished at
+        - if @ci_project && @ci_project.coverage_enabled?
+          %th Coverage
+        %th
+    = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried,
+             locals: { coverage: @ci_project.try(:coverage_enabled?) }
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index f8681024d1be73fb35b8af3ab0c837c069b8b075..30a3973828ff39cfd7139a8ab5f3899c539d5c64 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -1,5 +1,6 @@
 - page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
 = render "projects/commits/header_title"
 = render "commit_box"
+= render "ci_menu" if @ci_commit
 = render "projects/diffs/diffs", diffs: @diffs, project: @project
 = render "projects/notes/notes_with_form", view: params[:view]
diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..637154f56aa1d00c6562e99a9c1f811312bf940a
--- /dev/null
+++ b/app/views/projects/commit_statuses/_commit_status.html.haml
@@ -0,0 +1,54 @@
+%tr.commit_status
+  %td.status
+    = ci_status_with_icon(commit_status.status)
+
+  %td.commit_status-link
+    - if commit_status.target_url
+      = link_to commit_status.target_url do
+        %strong Build ##{commit_status.id}
+    - else
+      %strong Build ##{commit_status.id}
+
+    - if commit_status.show_warning?
+      %i.fa.fa-warning.text-warning
+
+  %td
+    = commit_status.ref
+
+  %td
+    = commit_status.stage
+
+  %td
+    = commit_status.name
+    .pull-right
+      - if commit_status.tags.any?
+        - commit_status.tags.each do |tag|
+          %span.label.label-primary
+            = tag
+      - if commit_status.try(:trigger_request)
+        %span.label.label-info triggered
+      - if commit_status.try(:allow_failure)
+        %span.label.label-danger allowed to fail
+
+  %td.duration
+    - if commit_status.duration
+      #{duration_in_words(commit_status.finished_at, commit_status.started_at)}
+
+  %td.timestamp
+    - if commit_status.finished_at
+      %span #{time_ago_in_words commit_status.finished_at} ago
+
+  - if defined?(coverage) && coverage
+    %td.coverage
+      - if commit_status.try(:coverage)
+        #{commit_status.coverage}%
+
+  %td
+    .pull-right
+      - if current_user && can?(current_user, :manage_builds, commit_status.gl_project)
+        - if commit_status.cancel_url
+          = link_to commit_status.cancel_url, title: 'Cancel' do
+            %i.fa.fa-remove.cred
+        - elsif defined?(allow_retry) && allow_retry && commit_status.retry_url
+          = link_to commit_status.retry_url, method: :post, title: 'Retry' do
+            %i.fa.fa-repeat
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 4617b188150ff80f65b9054f450842ef673a8326..9698921f6da74c326890fd06531b92266706f357 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -16,7 +16,7 @@
         - if diff_file.mode_changed?
           %span.file-mode= "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}"
 
-      .diff-btn-group
+      .diff-controls
         - if blob.text?
           = link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do
             %i.fa.fa-comments
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 90dce739992a8817667dd503c22254773c2c0acc..1882a82fba59c7aebcda86dad214508d91956906 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -193,13 +193,13 @@
         .panel.panel-default.panel.panel-danger
           .panel-heading Remove project
           .panel-body
-            = form_tag(namespace_project_path(@project.namespace, @project), method: :delete, html: { class: 'form-horizontal'}) do
+            = form_tag(namespace_project_path(@project.namespace, @project), method: :delete, class: 'form-horizontal') do
               %p
                 Removing the project will delete its repository and all related resources including issues, merge requests etc.
                 %br
                 %strong Removed projects cannot be restored!
 
-              = link_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) }
+              = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) }
       - else
         .nothing-here-block Only project owner can remove a project
 
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index cd5f3a5d39e4b7777b5bb8486f92f101f4461db3..f0b0a11c04a30de76383dd410d22bac157c3d580 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -1,36 +1,41 @@
 - page_title "Fork project"
-%h3.page-title Fork project
-%p.lead
-  Click to fork the project to a user or group
-%hr
+- if @namespaces.present?
+  %h3.page-title Fork project
+  %p.lead
+    Click to fork the project to a user or group
+  %hr
 
-.fork-namespaces
-  - @namespaces.in_groups_of(6, false) do |group|
-    .row
-      - group.each do |namespace|
-        .col-md-2.col-sm-3
-          - if fork = namespace.find_fork_of(@project)
-            .fork-thumbnail
-              = link_to project_path(fork), title: "Visit project fork", class: 'has_tooltip' do
-                = image_tag namespace_icon(namespace, 100)
-                .caption
-                  %strong
-                    = namespace.human_name
-                  %div.text-primary
-                    Already forked
+  .fork-namespaces
+    - @namespaces.in_groups_of(6, false) do |group|
+      .row
+        - group.each do |namespace|
+          .col-md-2.col-sm-3
+            - if fork = namespace.find_fork_of(@project)
+              .fork-thumbnail
+                = link_to project_path(fork), title: "Visit project fork", class: 'has_tooltip' do
+                  = image_tag namespace_icon(namespace, 100)
+                  .caption
+                    %strong
+                      = namespace.human_name
+                    %div.text-primary
+                      Already forked
 
-          - else
-            .fork-thumbnail
-              = link_to namespace_project_fork_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do
-                = image_tag namespace_icon(namespace, 100)
-                .caption
-                  %strong
-                    = namespace.human_name
+            - else
+              .fork-thumbnail
+                = link_to namespace_project_fork_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do
+                  = image_tag namespace_icon(namespace, 100)
+                  .caption
+                    %strong
+                      = namespace.human_name
 
-  %p.light
-    Fork is a copy of a project repository.
-    %br
-    Forking a repository allows you to do changes without affecting the original project.
+    %p.light
+      Fork is a copy of a project repository.
+      %br
+      Forking a repository allows you to do changes without affecting the original project.
+- else
+  %h3 No available namespaces to fork the project
+  %p.slead
+    You must have permission to create a project in a namespace before forking.
 
 .save-project-loader.hide
   .center
diff --git a/app/views/projects/labels/_form.html.haml b/app/views/projects/labels/_form.html.haml
index 534c545329b0a85f01bb45dc942020ab7915bc08..4cf13492e99cd4cfe0a67b3a2b0a4f69f9c4b93f 100644
--- a/app/views/projects/labels/_form.html.haml
+++ b/app/views/projects/labels/_form.html.haml
@@ -10,7 +10,7 @@
   .form-group
     = f.label :title, class: 'control-label'
     .col-sm-10
-      = f.text_field :title, class: "form-control", required: true
+      = f.text_field :title, class: "form-control js-quick-submit", required: true
   .form-group
     = f.label :color, "Background Color", class: 'control-label'
     .col-sm-10
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 0b0f52c653cf184dad3e6a0c31cfc43dad17d1e0..e7ac7a0eaa45df35e92666361cd73347ae9326c1 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -24,7 +24,7 @@
             %ul.dropdown-menu
               %li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch)
               %li= link_to "Plain Diff",    merge_request_path(@merge_request, format: :diff)
-      .light
+      .normal
         %span Request to merge
         %span.label-branch #{source_branch_with_namespace(@merge_request)}
         %span into
@@ -34,7 +34,7 @@
     = render "projects/merge_requests/widget/show.html.haml"
 
     - if @merge_request.open? && @merge_request.can_be_merged?
-      .light
+      .light.append-bottom-20
         You can also accept this merge request manually using the
         = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
 
diff --git a/app/views/projects/merge_requests/widget/_heading.html.haml b/app/views/projects/merge_requests/widget/_heading.html.haml
index 10640f746f01f61f92d3087dd001b18038c484d3..68dda1424cfa9b8d8aebe24922c8c671bdc074d5 100644
--- a/app/views/projects/merge_requests/widget/_heading.html.haml
+++ b/app/views/projects/merge_requests/widget/_heading.html.haml
@@ -1,30 +1,44 @@
 - if @merge_request.has_ci?
-  .mr-widget-heading
-    - [:success, :skipped, :canceled, :failed, :running, :pending].each do |status|
-      .ci_widget{class: "ci-#{status}", style: "display:none"}
-        - if status == :success
-          - status = "passed"
-          = icon("check-circle")
-        - else
-          = icon("circle")
+  - ci_commit = @merge_request.source_project.ci_commit(@merge_request.source_sha)
+  - if ci_commit
+    - status = ci_commit.status
+    .mr-widget-heading
+      .ci_widget{class: "ci-#{status}"}
+        = ci_status_icon(ci_commit)
         %span CI build #{status}
         for #{@merge_request.last_commit_short_sha}.
         %span.ci-coverage
-        - if ci_build_details_path(@merge_request)
-          = link_to "View build details", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
+        = link_to "View build details", ci_status_path(ci_commit)
 
-    .ci_widget
-      = icon("spinner spin")
-      Checking CI status for #{@merge_request.last_commit_short_sha}&hellip;
+  - else
+    - # Compatibility with old CI integrations (ex jenkins) when you request status from CI server via AJAX
+    - # Remove in later versions when services like Jenkins will set CI status via Commit status API
+    .mr-widget-heading
+      - [:success, :skipped, :canceled, :failed, :running, :pending].each do |status|
+        .ci_widget{class: "ci-#{status}", style: "display:none"}
+          - if status == :success
+            - status = "passed"
+            = icon("check-circle")
+          - else
+            = icon("circle")
+          %span CI build #{status}
+          for #{@merge_request.last_commit_short_sha}.
+          %span.ci-coverage
+          - if ci_build_details_path(@merge_request)
+            = link_to "View build details", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
 
-    .ci_widget.ci-not_found{style: "display:none"}
-      = icon("times-circle")
-      Could not find CI status for #{@merge_request.last_commit_short_sha}.
+      .ci_widget
+        = icon("spinner spin")
+        Checking CI status for #{@merge_request.last_commit_short_sha}&hellip;
 
-    .ci_widget.ci-error{style: "display:none"}
-      = icon("times-circle")
-      Could not connect to the CI server. Please check your settings and try again.
+      .ci_widget.ci-not_found{style: "display:none"}
+        = icon("times-circle")
+        Could not find CI status for #{@merge_request.last_commit_short_sha}.
 
-  :coffeescript
-    $ ->
-      merge_request_widget.getCiStatus()
+      .ci_widget.ci-error{style: "display:none"}
+        = icon("times-circle")
+        Could not connect to the CI server. Please check your settings and try again.
+
+    :coffeescript
+      $ ->
+        merge_request_widget.getCiStatus()
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index 74e9668052d60354ce8d66f0f4e40df2fef3c10b..255ddab479f4b3765eb37d15930540c8e35d2c20 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -16,13 +16,13 @@
       .form-group
         = f.label :title, "Title", class: "control-label"
         .col-sm-10
-          = f.text_field :title, maxlength: 255, class: "form-control", required: true
+          = f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true
           %p.hint Required
       .form-group.milestone-description
         = f.label :description, "Description", class: "control-label"
         .col-sm-10
           = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do
-            = render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
+            = render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit'
             .hint
               .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
               .pull-left Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index bccea21e7a82794f69880f112c44e4991de11031..daab2326bc7615d88c6a43ed6ae4b8f5fac58397 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -8,7 +8,7 @@
     = form_for @project, html: { class: 'new_project form-horizontal js-requires-input' } do |f|
       .form-group.project-name-holder
         = f.label :path, class: 'control-label' do
-          %strong Project path
+          Project path
         .col-sm-10
           .input-group
             = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 1, autofocus: true, required: true
@@ -23,7 +23,6 @@
             = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'select2', tabindex: 2}
 
       - if import_sources_enabled?
-        %hr
 
         .project-import.js-toggle-container
           .form-group
@@ -35,7 +34,7 @@
                     %i.fa.fa-github
                     GitHub
                 - else
-                  = link_to '#', class: 'how_to_import_link light btn import_github' do
+                  = link_to '#', class: 'how_to_import_link btn import_github' do
                     %i.fa.fa-github
                     GitHub
                   = render 'github_import_modal'
@@ -46,7 +45,7 @@
                     %i.fa.fa-bitbucket
                     Bitbucket
                 - else
-                  = link_to status_import_bitbucket_path, class: 'how_to_import_link light btn import_bitbucket', "data-no-turbolink" => "true" do
+                  = link_to status_import_bitbucket_path, class: 'how_to_import_link btn import_bitbucket', "data-no-turbolink" => "true" do
                     %i.fa.fa-bitbucket
                     Bitbucket
                   = render 'bitbucket_import_modal'
@@ -57,7 +56,7 @@
                     %i.fa.fa-heart
                     GitLab.com
                 - else
-                  = link_to status_import_gitlab_path, class: 'how_to_import_link light btn import_gitlab' do
+                  = link_to status_import_gitlab_path, class: 'how_to_import_link btn import_gitlab' do
                     %i.fa.fa-heart
                     GitLab.com
                   = render 'gitlab_import_modal'
@@ -97,7 +96,7 @@
                     %li
                       To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}.
 
-      %hr.prepend-botton-10
+      .prepend-botton-10
 
       .form-group
         = f.label :description, class: 'control-label' do
@@ -112,10 +111,11 @@
 
         - if current_user.can_create_group?
           .pull-right
-            .light
-              Need a group for several dependent projects?
-              = link_to new_group_path, class: "btn btn-xs" do
-                Create a group
+            .light.inline
+              .space-right
+                Need a group for several dependent projects?
+            = link_to new_group_path, class: "btn" do
+              Create a group
 
 .save-project-loader.hide
   .center
diff --git a/app/views/projects/notes/_edit_form.html.haml b/app/views/projects/notes/_edit_form.html.haml
index a0e26f9827e5e86d24079a23160dd79295b404b3..a21c019986a99a9316b8c12fb474a57895824630 100644
--- a/app/views/projects/notes/_edit_form.html.haml
+++ b/app/views/projects/notes/_edit_form.html.haml
@@ -2,7 +2,7 @@
   = form_for note, url: namespace_project_note_path(@project.namespace, @project, note), method: :put, remote: true, authenticity_token: true do |f|
     = note_target_fields(note)
     = render layout: 'projects/md_preview', locals: { preview_class: 'md-preview' } do
-      = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field'
+      = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field js-quick-submit'
       = render 'projects/notes/hints'
 
     .note-form-actions
diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml
index d99445da59ac5977711278a13cea860308c49367..13dfa0a1bb33fc48bda63410892bfb1fa2b998cb 100644
--- a/app/views/projects/notes/_form.html.haml
+++ b/app/views/projects/notes/_form.html.haml
@@ -8,12 +8,12 @@
   = f.hidden_field :noteable_type
 
   = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
-    = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text'
+    = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-quick-submit'
     = render 'projects/notes/hints'
     .error-alert
 
   .note-form-actions
     .buttons.clearfix
-      = f.submit 'Add Comment', class: "btn comment-btn btn-grouped js-comment-button"
+      = f.submit 'Add Comment', class: "btn btn-green comment-btn btn-grouped js-comment-button"
       = yield(:note_actions)
       %a.btn.grouped.js-close-discussion-note-form Cancel
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 9a0a824b811ab3a01a094b769e56401fe6ce7d06..82809bec5b81f49754c11d384e0e26e491b96e34 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -5,7 +5,7 @@
   .clearfix.js-toggle-container
     = 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 search-text-input' }
+        = 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'
 
     - if can?(current_user, :admin_project_member, @project)
diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml
index b9486a9b49265c92771b58c529b26fd9f51cb4de..07c24950ee238e89c7d5744d79ea54bd79d5db6d 100644
--- a/app/views/projects/repositories/_download_archive.html.haml
+++ b/app/views/projects/repositories/_download_archive.html.haml
@@ -3,10 +3,10 @@
 - split_button = split_button || false
 - if split_button == true
   %span.btn-group{class: btn_class}
-    = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn col-xs-10', rel: 'nofollow' do
+    = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn btn-success col-xs-10', rel: 'nofollow' do
       %i.fa.fa-download
       %span Download zip
-    %a.col-xs-2.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' }
+    %a.col-xs-2.btn.btn-success.dropdown-toggle{ 'data-toggle' => 'dropdown' }
       %span.caret
       %span.sr-only
         Select Archive Format
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index efa119edd5a36d086d345758dfd608a34c7e244f..e95d987d74c90f25a3bcb00acde0f7a1c03801ea 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -2,9 +2,10 @@
   - if current_user
     = auto_discovery_link_tag(:atom, namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "#{@project.name} activity")
 
-- if current_user && can?(current_user, :download_code, @project)
-  = render 'shared/no_ssh'
-  = render 'shared/no_password'
+= content_for :flash_message do
+  - if current_user && can?(current_user, :download_code, @project)
+    = render 'shared/no_ssh'
+    = render 'shared/no_password'
 
 - if prefer_readme?
   = render 'projects/last_push'
diff --git a/app/views/projects/tree/_readme.html.haml b/app/views/projects/tree/_readme.html.haml
index f082d71186558744fc0eba13427e81659c39c845..7e9af19c8ba015e3acf3efd511cca0ee0bce42d2 100644
--- a/app/views/projects/tree/_readme.html.haml
+++ b/app/views/projects/tree/_readme.html.haml
@@ -1,7 +1,8 @@
-%article.readme-holder#README
-  = link_to '#README' do
-    %h4.readme-file-title
-      %i.fa.fa-file
-      = readme.name
-  .wiki
+%article.file-holder.readme-holder#README
+  .file-title
+    = link_to '#README' do
+      %strong
+        %i.fa.fa-file
+        = readme.name
+  .file-content.wiki
     = render_readme(readme)
diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml
index 367a87927d7910662801a2351d9c0b170ae6f0cb..7ff48e32e601e8a349ad3dc1d1d1e63b9b34c1ed 100644
--- a/app/views/projects/tree/_tree.html.haml
+++ b/app/views/projects/tree/_tree.html.haml
@@ -1,51 +1,71 @@
-%ul.breadcrumb.repo-breadcrumb
-  %li
-    = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
-      = @project.path
-  - tree_breadcrumbs(tree, 6) do |title, path|
+.gray-content-block
+  %ul.breadcrumb.repo-breadcrumb
     %li
-      - if path
-        = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
-      - else
-        = link_to title, '#'
-  - if current_user && can_push_branch?(@project, @ref)
-    %li
-      = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'New file', id: 'new-file-link' do
-        %small
-          %i.fa.fa-plus
+      = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
+        = @project.path
+    - tree_breadcrumbs(tree, 6) do |title, path|
+      %li
+        - if path
+          = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
+        - else
+          = link_to title, '#'
+    - if allowed_tree_edit?
+      %li
+        %span.dropdown
+          %a.dropdown-toggle.btn.add-to-tree{href: '#', "data-toggle" => "dropdown"}
+            = icon('plus')
+          %ul.dropdown-menu
+            %li
+              = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'Create file', id: 'new-file-link' do
+                = icon('pencil fw')
+                Create file
+            %li
+              = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do
+                = icon('file fw')
+                Upload file
+            %li.divider
+            %li
+              = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do
+                = icon('folder fw')
+                New directory
 
-%div#tree-content-holder.tree-content-holder.prepend-top-20
-  %table#tree-slider{class: "table_#{@hex_path} tree-table" }
-    %thead
-      %tr
-        %th Name
-        %th Last Update
-        %th.hidden-xs
-          .pull-left Last Commit
-          .last-commit.hidden-sm.pull-left
-            &nbsp;
-            %i.fa.fa-angle-right
-            &nbsp;
-            %small.light
-              = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit)
-              &ndash;
-              = truncate(@commit.title, length: 50)
-          = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right'
+%div#tree-content-holder.tree-content-holder
+  .tree-table-holder
+    %table.table#tree-slider{class: "table_#{@hex_path} tree-table table-striped" }
+      %thead
+        %tr
+          %th Name
+          %th Last Update
+          %th.hidden-xs
+            .pull-left Last Commit
+            .last-commit.hidden-sm.pull-left
+              &nbsp;
+              %i.fa.fa-angle-right
+              &nbsp;
+              %small.light
+                = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit)
+                &ndash;
+                = truncate(@commit.title, length: 50)
+            = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right'
 
-    - if @path.present?
-      %tr.tree-item
-        %td.tree-item-file-name
-          = link_to "..", namespace_project_tree_path(@project.namespace, @project, up_dir_path), class: 'prepend-left-10'
-        %td
-        %td.hidden-xs
+      - if @path.present?
+        %tr.tree-item
+          %td.tree-item-file-name
+            = link_to "..", namespace_project_tree_path(@project.namespace, @project, up_dir_path), class: 'prepend-left-10'
+          %td
+          %td.hidden-xs
 
-    = render_tree(tree)
+      = render_tree(tree)
 
   - if tree.readme
     = render "projects/tree/readme", readme: tree.readme
 
 %div.tree_progress
 
+- if allowed_tree_edit?
+  = render 'projects/blob/upload', title: 'Upload', placeholder: 'Upload new file', button_title: 'Upload file', form_path: namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post
+  = render 'projects/blob/new_dir'
+
 :javascript
   // Load last commit log for each file in tree
   $('#tree-slider').waitForImages(function() {
diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml
index 05d754adbe5a8f58b75977c0eabd6a8f64bcd5ff..261d4a92d7d8006a32a0d80f23194a7e7b32d815 100644
--- a/app/views/projects/wikis/_form.html.haml
+++ b/app/views/projects/wikis/_form.html.haml
@@ -22,7 +22,7 @@
     = f.label :content, class: 'control-label'
     .col-sm-10
       = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do
-        = render 'projects/zen', f: f, attr: :content, classes: 'description form-control'
+        = render 'projects/zen', f: f, attr: :content, classes: 'description form-control js-quick-submit'
         .col-sm-12.hint
           .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}
           .pull-right Attach files by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml
index 03e6a522b251ae1b422f1bcc2b4d5d504d74af04..d179a1abec1323380c4de50cc3cdb40f7a1f46da 100644
--- a/app/views/projects/wikis/pages.html.haml
+++ b/app/views/projects/wikis/pages.html.haml
@@ -3,6 +3,7 @@
 
 = render 'nav'
 .gray-content-block
+  = render 'main_links'
   %h3.page-title
     All Pages
 %ul.content-list
diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml
index 3938c545caddd0bbbc7948b22026c83fbc3fc835..17b0981f073917fb08e66a8b8260d0f72d9ca41f 100644
--- a/app/views/search/_form.html.haml
+++ b/app/views/search/_form.html.haml
@@ -6,7 +6,7 @@
 
   .search-holder.clearfix
     .input-group
-      = search_field_tag :search, params[:search], placeholder: "Search for projects, issues etc", class: "form-control search-text-input", id: "dashboard_search", autofocus: true
+      = search_field_tag :search, params[:search], placeholder: "Search for projects, issues etc", class: "form-control search-text-input", id: "dashboard_search", autofocus: true, spellcheck: false
       %span.input-group-btn
         = button_tag 'Search', class: "btn btn-primary"
     - unless params[:snippets].eql? 'true'
diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml
index 5071ff640f18c08bbe3d0bf0e565defe32221b38..cc3f1268f8b9fb8d01dcc87ecc3dcee30c51646b 100644
--- a/app/views/shared/_commit_message_container.html.haml
+++ b/app/views/shared/_commit_message_container.html.haml
@@ -6,7 +6,7 @@
       .max-width-marker
       = text_area_tag 'commit_message',
           (params[:commit_message] || local_assigns[:text]),
-          class: 'form-control', placeholder: local_assigns[:placeholder],
+          class: 'form-control js-quick-submit', placeholder: local_assigns[:placeholder],
           required: true, rows: (local_assigns[:rows] || 3)
     - if local_assigns[:hint]
       %p.hint
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 33ec726e93c9687ab98c037c490901ab8a46d91a..594e54f404c155ac0767780e4968dece3a9c4900 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -10,7 +10,7 @@
     %strong= 'Title *'
   .col-sm-10
     = f.text_field :title, maxlength: 255, autofocus: true, autocomplete: 'off',
-        class: 'form-control pad js-gfm-input', required: true
+        class: 'form-control pad js-gfm-input js-quick-submit', required: true
 
     - if issuable.is_a?(MergeRequest)
       %p.help-block
@@ -26,7 +26,7 @@
 
     = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
       = render 'projects/zen', f: f, attr: :description,
-                               classes: 'description form-control'
+                               classes: 'description form-control js-quick-submit'
       .col-sm-12.hint
         .pull-left
           Parsed with
diff --git a/app/views/shared/issuable/_search_form.html.haml b/app/views/shared/issuable/_search_form.html.haml
index 58c3de64b77727b4a6fe2d1d494e2e01f39535b3..3a5ad00aa91a7c63b045bab87a6b292a5f296ea9 100644
--- a/app/views/shared/issuable/_search_form.html.haml
+++ b/app/views/shared/issuable/_search_form.html.haml
@@ -1,6 +1,6 @@
 = form_tag(path, method: :get, id: "issue_search_form", class: 'pull-left issue-search-form') do
   .append-right-10.hidden-xs.hidden-sm
-    = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input' }
+    = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input', spellcheck: false }
     = hidden_field_tag :state, params['state']
     = hidden_field_tag :scope, params['scope']
     = hidden_field_tag :assignee_id, params['assignee_id']
diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml
index 16e1d8421ded3c7fcb7d5fa406e3014481f2d880..357cfd6a37007542ca262155848ece0f66d85b06 100644
--- a/app/views/shared/projects/_list.html.haml
+++ b/app/views/shared/projects/_list.html.haml
@@ -2,11 +2,12 @@
 - avatar = true unless local_assigns[:avatar] == false
 - stars = true unless local_assigns[:stars] == false
 - ci = false unless local_assigns[:ci] == true
+- skip_namespace = false unless local_assigns[:skip_namespace] == true
 
 %ul.projects-list
   - projects.each_with_index do |project, i|
     - css_class = (i >= projects_limit) ? 'hide' : nil
-    = render "shared/projects/project", project: project,
+    = render "shared/projects/project", project: project, skip_namespace: skip_namespace,
       avatar: avatar, stars: stars, css_class: css_class, ci: ci
 
   - if projects.size > projects_limit
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index e67e5a8a6387c21381e86d60a8498b0de703ecd3..aee839b44e7ee43d15749ec3215142c606f56a4b 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -1,6 +1,7 @@
 - avatar = true unless local_assigns[:avatar] == false
 - stars = true unless local_assigns[:stars] == false
 - ci = false unless local_assigns[:ci] == true
+- skip_namespace = false unless local_assigns[:skip_namespace] == true
 - css_class = '' unless local_assigns[:css_class]
 - css_class += " no-description" unless project.description.present?
 %li.project-row{ class: css_class }
@@ -11,7 +12,7 @@
           = project_icon(project, alt: '', class: 'avatar project-avatar s46')
       %span.project-full-name
         %span.namespace-name
-          - if project.namespace
+          - if project.namespace && !skip_namespace
             = project.namespace.human_name
             \/
         %span.project-name.filter-title
diff --git a/config/application.rb b/config/application.rb
index a96e22211e640a4b826552cd9ce4d61a46ff4885..bfa2a809dd7d7fd472990b00d6f38c8948fd36ce 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -74,7 +74,7 @@ module Gitlab
         origins '*'
         resource '/api/*',
           headers: :any,
-          methods: [:get, :post, :options, :put, :delete],
+          methods: :any,
           expose: ['Link']
       end
     end
diff --git a/config/mail_room.yml.example b/config/mail_room.yml.example
index 82e1a42058e1e9d7a23155449a82b63ce421d02c..bb624e8a187d4bccdafabd11994d4c6b02463712 100644
--- a/config/mail_room.yml.example
+++ b/config/mail_room.yml.example
@@ -9,11 +9,13 @@
     # # Whether the IMAP server uses StartTLS
     # :start_tls: false
     # # Email account username. Usually the full email address.
-    # :email: "replies@gitlab.example.com"
+    # :email: "gitlab-incoming@gmail.com"
     # # Email account password
     # :password: "password"
+
     # # The name of the mailbox where incoming mail will end up. Usually "inbox".
     # :name: "inbox"
+
     # # Always "sidekiq".
     # :delivery_method: sidekiq
     # # Always true.
@@ -25,5 +27,13 @@
     #   :namespace: resque:gitlab
     #   # Always "incoming_email".
     #   :queue: incoming_email
-    #   # Always "EmailReceiverWorker"
+    #   # Always "EmailReceiverWorker".
     #   :worker: EmailReceiverWorker
+
+    # # Always "redis".
+    # :arbitration_method: redis
+    # :arbitration_options:
+    #   # The URL to the Redis server. Should match the URL in config/resque.yml.
+    #   :redis_url: redis://localhost:6379
+    #   # Always "mail_room:gitlab".
+    #   :namespace: mail_room:gitlab
diff --git a/config/routes.rb b/config/routes.rb
index a21889631ed7a2d09b62ab9d4fdcda9b1a35ab64..8e6fbf6340c0cf39e351de8eaeb4d9e2f7a44cf4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -22,29 +22,6 @@ Gitlab::Application.routes.draw do
         get :dumped_yaml
       end
 
-      resources :services, only: [:index, :edit, :update] do
-        member do
-          get :test
-        end
-      end
-
-      resource :charts, only: [:show]
-
-      resources :commits, only: [:show] do
-        member do
-          get :status
-          get :cancel
-        end
-      end
-
-      resources :builds, only: [:show] do
-        member do
-          get :cancel
-          get :status
-          post :retry
-        end
-      end
-
       resources :runner_projects, only: [:create, :destroy]
 
       resources :events, only: [:index]
@@ -465,6 +442,15 @@ Gitlab::Application.routes.draw do
           )
         end
 
+        scope do
+          post(
+              '/create_dir/*id',
+              to: 'tree#create_dir',
+              constraints: { id: /.+/ },
+              as: 'create_dir'
+          )
+        end
+
         scope do
           get(
             '/blame/*id',
@@ -485,7 +471,11 @@ Gitlab::Application.routes.draw do
 
         resource  :avatar, only: [:show, :destroy]
         resources :commit, only: [:show], constraints: { id: /[[:alnum:]]{6,40}/ } do
-          get :branches, on: :member
+          member do
+            get :branches
+            get :ci
+            get :cancel_builds
+          end
         end
 
         resources :compare, only: [:index, :create]
@@ -589,6 +579,20 @@ Gitlab::Application.routes.draw do
           end
         end
 
+        resources :ci_services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do
+          member do
+            get :test
+          end
+        end
+
+        resources :builds, only: [:show] do
+          member do
+            get :cancel
+            get :status
+            post :retry
+          end
+        end
+
         resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do
           member do
             get :test
diff --git a/db/fixtures/development/04_project.rb b/db/fixtures/development/04_project.rb
index 8f71198e47f9de7a1cc061148dfcb563d9a6084f..b463999996747aaeb53e31af3f2b0b21ea2c6422 100644
--- a/db/fixtures/development/04_project.rb
+++ b/db/fixtures/development/04_project.rb
@@ -73,8 +73,13 @@ Sidekiq::Testing.inline! do
       }
 
       project = Projects::CreateService.new(User.first, params).execute
+      # Seed-Fu runs this entire fixture in a transaction, so the `after_commit`
+      # hook won't run until after the fixture is loaded. That is too late
+      # since the Sidekiq::Testing block has already exited. Force clearing
+      # the `after_commit` queue to ensure the job is run now.
+      project.send(:_run_after_commit_queue)
 
-      if project.valid?
+      if project.valid? && project.valid_repo?
         print '.'
       else
         puts project.errors.full_messages
diff --git a/db/migrate/20151007120511_namespaces_projects_path_lower_indexes.rb b/db/migrate/20151007120511_namespaces_projects_path_lower_indexes.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7f6cd6d5a78a670a5d0820b3ee881aaa97c8da57
--- /dev/null
+++ b/db/migrate/20151007120511_namespaces_projects_path_lower_indexes.rb
@@ -0,0 +1,17 @@
+class NamespacesProjectsPathLowerIndexes < ActiveRecord::Migration
+  disable_ddl_transaction!
+
+  def up
+    return unless Gitlab::Database.postgresql?
+
+    execute 'CREATE INDEX CONCURRENTLY index_on_namespaces_lower_path ON namespaces (LOWER(path));'
+    execute 'CREATE INDEX CONCURRENTLY index_on_projects_lower_path ON projects (LOWER(path));'
+  end
+
+  def down
+    return unless Gitlab::Database.postgresql?
+
+    remove_index :namespaces, name: :index_on_namespaces_lower_path
+    remove_index :projects, name: :index_on_projects_lower_path
+  end
+end
diff --git a/db/migrate/20151008123042_add_type_and_description_to_builds.rb b/db/migrate/20151008123042_add_type_and_description_to_builds.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c72b1c611c6db7125921b5f2aebe8f3aa884661e
--- /dev/null
+++ b/db/migrate/20151008123042_add_type_and_description_to_builds.rb
@@ -0,0 +1,9 @@
+class AddTypeAndDescriptionToBuilds < ActiveRecord::Migration
+  def change
+    add_column :ci_builds, :type, :string
+    add_column :ci_builds, :target_url, :string
+    add_column :ci_builds, :description, :string
+    add_index :ci_builds, [:commit_id, :type, :ref]
+    add_index :ci_builds, [:commit_id, :type, :name, :ref]
+  end
+end
diff --git a/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb b/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f5c44babd84277d0b7764942a114c54f7e1b32fb
--- /dev/null
+++ b/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb
@@ -0,0 +1,5 @@
+class MigrateNameToDescriptionForBuilds < ActiveRecord::Migration
+  def change
+    execute("UPDATE ci_builds SET type='Ci::Build' WHERE type IS NULL")
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 93202f16111d4e9d4fbed17e662b1574168c0a8c..7a11dfca03422fcc090afbc39ef469dff12191dd 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20151005162154) do
+ActiveRecord::Schema.define(version: 20151008130321) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -103,9 +103,14 @@ ActiveRecord::Schema.define(version: 20151005162154) do
     t.boolean  "tag"
     t.string   "ref"
     t.integer  "user_id"
+    t.string   "type"
+    t.string   "target_url"
+    t.string   "description"
   end
 
   add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
+  add_index "ci_builds", ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree
+  add_index "ci_builds", ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref", using: :btree
   add_index "ci_builds", ["commit_id"], name: "index_ci_builds_on_commit_id", using: :btree
   add_index "ci_builds", ["project_id", "commit_id"], name: "index_ci_builds_on_project_id_and_commit_id", using: :btree
   add_index "ci_builds", ["project_id"], name: "index_ci_builds_on_project_id", using: :btree
diff --git a/doc/api/commits.md b/doc/api/commits.md
index eb8d6a43592a0f2210317c59719fac951e9ca36a..9f72adc6ed9ac22a6233ecb4d7e0bb30465f6bac 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -62,7 +62,8 @@ Parameters:
   "authored_date": "2012-09-20T09:06:12+03:00",
   "parent_ids": [
     "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
-  ]
+  ],
+  "status": "running"
 }
 ```
 
@@ -156,3 +157,84 @@ Parameters:
   "line_type": "new"
 }
 ```
+
+## Get the status of a commit
+
+Get the statuses of a commit in a project.
+
+```
+GET /projects/:id/repository/commits/:sha/statuses
+```
+
+Parameters:
+
+- `id` (required) - The ID of a project
+- `sha` (required) - The commit SHA
+- `ref` (optional) - Filter by ref name, it can be branch or tag
+- `stage` (optional) - Filter by stage
+- `name` (optional) - Filer by status name, eg. jenkins
+- `all` (optional) - The flag to return all statuses, not only latest ones
+
+```json
+[
+  {
+    "id": 13,
+    "sha": "b0b3a907f41409829b307a28b82fdbd552ee5a27",
+    "ref": "test",
+    "status": "success",
+    "name": "ci/jenkins",
+    "target_url": "http://jenkins/project/url",
+    "description": "Jenkins success",
+    "created_at": "2015-10-12T09:47:16.250Z",
+    "started_at": "2015-10-12T09:47:16.250Z"",
+    "finished_at": "2015-10-12T09:47:16.262Z",
+    "author": {
+      "id": 1,
+      "username": "admin",
+      "email": "admin@local.host",
+      "name": "Administrator",
+      "blocked": false,
+      "created_at": "2012-04-29T08:46:00Z"
+    }
+  }
+]
+```
+
+## Post the status to commit
+
+Adds or updates a status of a commit.
+
+```
+POST /projects/:id/statuses/:sha
+```
+
+- `id` (required) - The ID of a project
+- `sha` (required) - The commit SHA
+- `state` (required) - The state of the status. Can be: pending, running, success, failed, canceled
+- `ref` (optional) - The ref (branch or tag) to which the status refers
+- `name` or `context` (optional) - The label to differentiate this status from the status of other systems. Default: "default"
+- `target_url` (optional) - The target URL to associate with this status
+- `description` (optional) - The short description of the status
+
+```json
+{
+  "id": 13,
+  "sha": "b0b3a907f41409829b307a28b82fdbd552ee5a27",
+  "ref": "test",
+  "status": "success",
+  "name": "ci/jenkins",
+  "target_url": "http://jenkins/project/url",
+  "description": "Jenkins success",
+  "created_at": "2015-10-12T09:47:16.250Z",
+  "started_at": "2015-10-12T09:47:16.250Z"",
+  "finished_at": "2015-10-12T09:47:16.262Z",
+  "author": {
+    "id": 1,
+    "username": "admin",
+    "email": "admin@local.host",
+    "name": "Administrator",
+    "blocked": false,
+    "created_at": "2012-04-29T08:46:00Z"
+  }
+}
+```
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index bb551fc67f751dd7029b50416fb0d7e54ac313d6..ffa7f2cdf14d388d6c1bfaff2e3d73863168c73a 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -188,6 +188,7 @@ Parameters:
 - `title` (required)             - Title of MR
 - `description` (optional)       - Description of MR
 - `target_project_id` (optional) - The target project (numeric id)
+- `labels` (optional)            - Labels for MR as a comma-separated list
 
 ```json
 {
@@ -239,6 +240,7 @@ Parameters:
 - `title`                       - Title of MR
 - `description`                 - Description of MR
 - `state_event`                 - New state (close|reopen|merge)
+- `labels` (optional)           - Labels for MR as a comma-separated list
 
 ```json
 {
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 04c6bf1e3a3a7037200b1a91acb265ead531a71a..022afb700424c25eab121cc08d00e667d4999e7f 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -15,21 +15,27 @@ The API_TOKEN will take the Secure Variable value: `SECURE`.
 
 ### Predefined variables (Environment Variables)
 
-| Variable                | Description |
+| Variable                | Runner | Description |
 |-------------------------|-------------|
-| **CI**                  | Mark that build is executed in CI environment |
-| **GITLAB_CI**           | Mark that build is executed in GitLab CI environment |
-| **CI_SERVER**           | Mark that build is executed in CI environment |
-| **CI_SERVER_NAME**      | CI server that is used to coordinate builds |
-| **CI_SERVER_VERSION**   | Not yet defined |
-| **CI_SERVER_REVISION**  | Not yet defined |
-| **CI_BUILD_REF**        | The commit revision for which project is built |
-| **CI_BUILD_BEFORE_SHA** | The first commit that were included in push request |
-| **CI_BUILD_REF_NAME**   | The branch or tag name for which project is built |
-| **CI_BUILD_ID**         | The unique id of the current build that GitLab CI uses internally |
-| **CI_BUILD_REPO**       | The URL to clone the Git repository |
-| **CI_PROJECT_ID**       | The unique id of the current project that GitLab CI uses internally |
-| **CI_PROJECT_DIR**      | The full path where the repository is cloned and where the build is ran |
+| **CI**                  | 0.4 | Mark that build is executed in CI environment |
+| **GITLAB_CI**           | all | Mark that build is executed in GitLab CI environment |
+| **CI_SERVER**           | all | Mark that build is executed in CI environment |
+| **CI_SERVER_NAME**      | all | CI server that is used to coordinate builds |
+| **CI_SERVER_VERSION**   | all | Not yet defined |
+| **CI_SERVER_REVISION**  | all | Not yet defined |
+| **CI_BUILD_REF**        | all | The commit revision for which project is built |
+| **CI_BUILD_TAG**        | 0.5 | The commit tag name. Present only when building tags. |
+| **CI_BUILD_NAME**       | 0.5 | The name of the build as defined in `.gitlab-ci.yml` |
+| **CI_BUILD_STAGE**      | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
+| **CI_BUILD_BEFORE_SHA** | all | The first commit that were included in push request |
+| **CI_BUILD_REF_NAME**   | all | The branch or tag name for which project is built |
+| **CI_BUILD_ID**         | all | The unique id of the current build that GitLab CI uses internally |
+| **CI_BUILD_REPO**       | all | The URL to clone the Git repository |
+| **CI_BUILD_TRIGGERED**  | 0.5 | The flag to indicate that build was triggered |
+| **CI_PROJECT_ID**       | all | The unique id of the current project that GitLab CI uses internally |
+| **CI_PROJECT_DIR**      | all | The full path where the repository is cloned and where the build is ran |
+
+**Some of the variables are only available when using runner with at least defined version.**
 
 Example values:
 
@@ -39,6 +45,10 @@ export CI_BUILD_ID="50"
 export CI_BUILD_REF="1ecfd275763eff1d6b4844ea3168962458c9f27a"
 export CI_BUILD_REF_NAME="master"
 export CI_BUILD_REPO="https://gitlab.com/gitlab-org/gitlab-ce.git"
+export CI_BUILD_TAG="1.0.0"
+export CI_BUILD_NAME="spec:other"
+export CI_BUILD_STAGE="test"
+export CI_BUILD_TRIGGERED="true"
 export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-ce"
 export CI_PROJECT_ID="34"
 export CI_SERVER="yes"
diff --git a/doc/customization/welcome_message.md b/doc/customization/welcome_message.md
index 6c141d1fb7a1ef39481e11943d6ae98f979aa983..e993230bb8806a109187a73a5f6a92906a4b2356 100644
--- a/doc/customization/welcome_message.md
+++ b/doc/customization/welcome_message.md
@@ -8,31 +8,5 @@ It is possible to add a markdown-formatted welcome message to your GitLab
 sign-in page. Users of GitLab Enterprise Edition should use the [branded login
 page feature](/ee/customization/branded_login_page.html) instead.
 
-## Omnibus-gitlab example
-
-In `/etc/gitlab/gitlab.rb`:
-
-```ruby
-gitlab_rails['extra_sign_in_text'] = <<'EOS'
-# ACME GitLab
-Welcome to the [ACME](http://www.example.com) GitLab server!
-EOS
-```
-
-Run `sudo gitlab-ctl reconfigure` for changes to take effect.
-
-## Installation from source
-
-In `/home/git/gitlab/config/gitlab.yml`:
-
-```yaml
-# snip
-production:
-  # snip
-  extra:
-    sign_in_text: |
-      # ACME GitLab
-      Welcome to the [ACME](http://www.example.com) GitLab server!
-```      
-
-Run `sudo service gitlab reload` for the change to take effect.
+The welcome message (extra_sign_in_text) can now be set/changed in the Admin UI.  
+Admin area > Settings
\ No newline at end of file
diff --git a/doc/incoming_email/README.md b/doc/incoming_email/README.md
index 316746ab54dd9ca88c2ed7780ab2f3313f41209c..aafa2345fab1506d275beb30270f5cf1d1d757a9 100644
--- a/doc/incoming_email/README.md
+++ b/doc/incoming_email/README.md
@@ -2,10 +2,6 @@
 
 GitLab can be set up to allow users to comment on issues and merge requests by replying to notification emails.
 
-**Warning**: Do not enable Reply by email if you have **multiple GitLab application servers**. 
-Due to an issue with the way incoming emails are read from the mail server, every incoming reply-by-email email will result in as many comments being created as you have application servers.
-[A fix is being worked on.](https://github.com/tpitale/mail_room/issues/46)
-
 ## Get a mailbox
 
 Reply by email requires an IMAP-enabled email account, with a provider or server that supports [email sub-addressing](https://en.wikipedia.org/wiki/Email_address#Sub-addressing). Sub-addressing is a feature where any email to `user+some_arbitrary_tag@example.com` will end up in the mailbox for `user@example.com`, and is supported by providers such as Gmail, Yahoo! Mail, Outlook.com and iCloud, as well as the Postfix mail server which you can run on-premises.
@@ -16,24 +12,35 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow [these
 
 ## Set it up
 
-In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
-
 ### Omnibus package installations
 
 1. Find the `incoming_email` section in `/etc/gitlab/gitlab.rb`, enable the feature, enter the email address including a placeholder for the `key` that references the item being replied to and fill in the details for your specific IMAP server and email account:
 
     ```ruby
+    # Postfix mail server, assumes mailbox incoming@gitlab.example.com
+    gitlab_rails['incoming_email_enabled'] = true
+    gitlab_rails['incoming_email_address'] = "incoming+%{key}@gitlab.example.com"
+    gitlab_rails['incoming_email_host'] = "gitlab.example.com" # IMAP server host
+    gitlab_rails['incoming_email_port'] = 143 # IMAP server port
+    gitlab_rails['incoming_email_ssl'] = false # Whether the IMAP server uses SSL
+    gitlab_rails['incoming_email_email'] = "incoming"  # Email account username. Usually the full email address.
+    gitlab_rails['incoming_email_password'] = "[REDACTED]" # Email account password
+    gitlab_rails['incoming_email_mailbox_name'] = "inbox" # The name of the mailbox where incoming mail will end up. Usually "inbox".
+    ```
+
+    ```ruby
+    # Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
     gitlab_rails['incoming_email_enabled'] = true
     gitlab_rails['incoming_email_address'] = "gitlab-incoming+%{key}@gmail.com"
     gitlab_rails['incoming_email_host'] = "imap.gmail.com" # IMAP server host
     gitlab_rails['incoming_email_port'] = 993 # IMAP server port
     gitlab_rails['incoming_email_ssl'] = true # Whether the IMAP server uses SSL
     gitlab_rails['incoming_email_email'] = "gitlab-incoming@gmail.com"  # Email account username. Usually the full email address.
-    gitlab_rails['incoming_email_password'] = "password" # Email account password
+    gitlab_rails['incoming_email_password'] = "[REDACTED]" # Email account password
     gitlab_rails['incoming_email_mailbox_name'] = "inbox" # The name of the mailbox where incoming mail will end up. Usually "inbox".
     ```
 
-    As mentioned, the part after `+` in the address is ignored, and any email sent here will end up in the mailbox for `gitlab-incoming@gmail.com`.
+    As mentioned, the part after `+` in the address is ignored, and any email sent here will end up in the mailbox for `incoming@gitlab.example.com`/`gitlab-incoming@gmail.com`.
 
 1. Reconfigure GitLab for the changes to take effect:
 
@@ -64,12 +71,20 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
     ```
 
     ```yaml
+    # Postfix mail server, assumes mailbox incoming@gitlab.example.com
+    incoming_email:
+      enabled: true
+      address: "incoming+%{key}@gitlab.example.com"
+    ```
+
+    ```yaml
+    # Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
     incoming_email:
       enabled: true
       address: "gitlab-incoming+%{key}@gmail.com"
     ```
 
-    As mentioned, the part after `+` in the address is ignored, and any email sent here will end up in the mailbox for `gitlab-incoming@gmail.com`.
+    As mentioned, the part after `+` in the address is ignored, and any email sent here will end up in the mailbox for `incoming@gitlab.example.com`/`gitlab-incoming@gmail.com`.
 
 2. Copy `config/mail_room.yml.example` to `config/mail_room.yml`:
 
@@ -84,6 +99,50 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
     ```
 
     ```yaml
+    # Postfix mail server
+    :mailboxes:
+      -
+        # IMAP server host
+        :host: "gitlab.example.com"
+        # IMAP server port
+        :port: 143
+        # Whether the IMAP server uses SSL
+        :ssl: false
+        # Whether the IMAP server uses StartTLS
+        :start_tls: false
+        # Email account username. Usually the full email address.
+        :email: "incoming"
+        # Email account password
+        :password: "[REDACTED]"
+
+        # The name of the mailbox where incoming mail will end up. Usually "inbox".
+        :name: "inbox"
+
+        # Always "sidekiq".
+        :delivery_method: sidekiq
+        # Always true.
+        :delete_after_delivery: true
+        :delivery_options:
+          # The URL to the Redis server used by Sidekiq. Should match the URL in config/resque.yml.
+          :redis_url: redis://localhost:6379
+          # Always "resque:gitlab".
+          :namespace: resque:gitlab
+          # Always "incoming_email".
+          :queue: incoming_email
+          # Always "EmailReceiverWorker"
+          :worker: EmailReceiverWorker
+
+        # Always "redis".
+        :arbitration_method: redis
+        :arbitration_options:
+          # The URL to the Redis server. Should match the URL in config/resque.yml.
+          :redis_url: redis://localhost:6379
+          # Always "mail_room:gitlab".
+          :namespace: mail_room:gitlab
+    ```
+
+    ```yaml
+    # Gmail / Google Apps
     :mailboxes:
       -
         # IMAP server host
@@ -98,8 +157,10 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
         :email: "gitlab-incoming@gmail.com"
         # Email account password
         :password: "[REDACTED]"
+
         # The name of the mailbox where incoming mail will end up. Usually "inbox".
         :name: "inbox"
+
         # Always "sidekiq".
         :delivery_method: sidekiq
         # Always true.
@@ -113,6 +174,14 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
           :queue: incoming_email
           # Always "EmailReceiverWorker"
           :worker: EmailReceiverWorker
+
+        # Always "redis".
+        :arbitration_method: redis
+        :arbitration_options:
+          # The URL to the Redis server. Should match the URL in config/resque.yml.
+          :redis_url: redis://localhost:6379
+          # Always "mail_room:gitlab".
+          :namespace: mail_room:gitlab
     ```
 
 5. Edit the init script configuration at `/etc/default/gitlab` to enable `mail_room`:
@@ -143,6 +212,7 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
 1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature and enter the email address including a placeholder for the `key` that references the item being replied to:
 
     ```yaml
+    # Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
     incoming_email:
       enabled: true
       address: "gitlab-incoming+%{key}@gmail.com"
@@ -159,6 +229,7 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
 3. Uncomment the configuration options in `config/mail_room.yml` and fill in the details for your specific IMAP server and email account:
 
     ```yaml
+    # Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
     :mailboxes:
       -
         # IMAP server host
@@ -173,8 +244,10 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
         :email: "gitlab-incoming@gmail.com"
         # Email account password
         :password: "[REDACTED]"
+
         # The name of the mailbox where incoming mail will end up. Usually "inbox".
         :name: "inbox"
+
         # Always "sidekiq".
         :delivery_method: sidekiq
         # Always true.
@@ -188,6 +261,14 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
           :queue: incoming_email
           # Always "EmailReceiverWorker"
           :worker: EmailReceiverWorker
+
+        # Always "redis".
+        :arbitration_method: redis
+        :arbitration_options:
+          # The URL to the Redis server. Should match the URL in config/resque.yml.
+          :redis_url: redis://localhost:6379
+          # Always "mail_room:gitlab".
+          :namespace: mail_room:gitlab
     ```
 
 4. Uncomment the `mail_room` line in your `Procfile`:
@@ -208,4 +289,4 @@ In this example, we'll use the Gmail address `gitlab-incoming@gmail.com`.
     bundle exec rake gitlab:incoming_email:check RAILS_ENV=development
     ```
 
-8. Reply by email should now be working.
\ No newline at end of file
+8. Reply by email should now be working.
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index 4fbd20762da60f9d89ef09c3c0df99ad56f542a3..629d38efc5355042124c94a0a9c88ba73a7a32aa 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -56,3 +56,17 @@ bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production
 ```
 block_auto_created_users: false
 ```
+
+## Disable Two-factor Authentication (2FA) for all users
+
+This task will disable 2FA for all users that have it enabled. This can be
+useful if GitLab's `.secret` file has been lost and users are unable to login,
+for example.
+
+```bash
+# omnibus-gitlab
+sudo gitlab-rake gitlab:two_factor:disable_for_all_users
+
+# installation from source
+bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_ENV=production
+```
diff --git a/doc/release/monthly.md b/doc/release/monthly.md
index c56e99a7005e1677278b8d2bad637aab8b7b368b..bd8a67d1d85a81f438db55db5cbb6c0449db1bf9 100644
--- a/doc/release/monthly.md
+++ b/doc/release/monthly.md
@@ -74,20 +74,19 @@ Xth: (1 working day before the 22nd)
 - [ ] Update GitLab.com with the latest RC (#LINK)
 - [ ] Update ci.gitLab.com with the latest RC (#LINK)
 
-22nd before 12AM CET:
+22nd before 1200 CET:
 
-Release before 12AM CET / 3AM PST, to make sure the majority of our users
+Release before 1200 CET / 2AM PST, to make sure the majority of our users
 get the new version on the 22nd and there is sufficient time in the European
 workday to quickly fix any issues.
 
 - [ ] Merge CE stable into EE stable (#LINK)
 - [ ] Create the 'x.y.0' tag with the [release tools](https://dev.gitlab.org/gitlab/release-tools) (#LINK)
 - [ ] Create the 'x.y.0' version on version.gitlab.com
-- [ ] Try to do before 11AM CET: Create and push omnibus tags for x.y.0 (will auto-release the packages) (#LINK)
-- [ ] Try to do before 12AM CET: Publish the release blog post (#LINK)
+- [ ] Try to do before 1100 CET: Create and push omnibus tags for x.y.0 (will auto-release the packages) (#LINK)
+- [ ] Try to do before 1200 CET: Publish the release blog post (#LINK)
 - [ ] Tweet about the release (blog post) (#LINK)
-- [ ] Schedule a second tweet of the release announcement with the same text at 6PM CET / 9AM PST
-
+- [ ] Schedule a second tweet of the release announcement with the same text at 1800 CET / 8AM PST
 ```
 
 - - -
@@ -223,4 +222,4 @@ Consider creating a post on Hacker News.
 
 ## Create a WIP blogpost for the next release
 
-Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md).
\ No newline at end of file
+Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md).
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index b0e4613cdefb712a07f0f501197e8abd1ecdcf15..5cb05b13b3ec8c945452e6155feec426d0938474 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -48,16 +48,17 @@ X-Gitlab-Event: System Hook
 
 ```json
 {
-         "created_at": "2012-07-21T07:30:56Z",
-         "event_name": "user_add_to_team",
-     "project_access": "Master",
-         "project_id": 74,
-       "project_name": "StoreCloud",
-       "project_path": "storecloud",
-         "user_email": "johnsmith@gmail.com",
-          "user_name": "John Smith",
-            "user_id": 41,
- "project_visibility": "private",
+                  "created_at": "2012-07-21T07:30:56Z",
+                  "event_name": "user_add_to_team",
+              "project_access": "Master",
+                  "project_id": 74,
+                "project_name": "StoreCloud",
+                "project_path": "storecloud",
+ "project_path_with_namespace": "jsmith/storecloud",
+                  "user_email": "johnsmith@gmail.com",
+                   "user_name": "John Smith",
+                     "user_id": 41,
+          "project_visibility": "private",
 }
 ```
 
@@ -65,16 +66,17 @@ X-Gitlab-Event: System Hook
 
 ```json
 {
-         "created_at": "2012-07-21T07:30:56Z",
-         "event_name": "user_remove_from_team",
-     "project_access": "Master",
-         "project_id": 74,
-       "project_name": "StoreCloud",
-       "project_path": "storecloud",
-         "user_email": "johnsmith@gmail.com",
-          "user_name": "John Smith",
-            "user_id": 41,
- "project_visibility": "private",
+                  "created_at": "2012-07-21T07:30:56Z",
+                  "event_name": "user_remove_from_team",
+              "project_access": "Master",
+                  "project_id": 74,
+                "project_name": "StoreCloud",
+                "project_path": "storecloud",
+ "project_path_with_namespace": "jsmith/storecloud",
+                  "user_email": "johnsmith@gmail.com",
+                   "user_name": "John Smith",
+                     "user_id": 41,
+          "project_visibility": "private",
 }
 ```
 
diff --git a/doc/update/7.14-to-8.0.md b/doc/update/7.14-to-8.0.md
index 0e65c32098c1d95cadb1733351d3a2251aff71e0..7ad4935e83979a4f11858154d43ca27ece0e6b8f 100644
--- a/doc/update/7.14-to-8.0.md
+++ b/doc/update/7.14-to-8.0.md
@@ -175,12 +175,21 @@ Also note that because Apache does not support upstreams behind Unix sockets you
 Now, GitLab CE and EE has CI integrated. However, migrations don't happen automatically and you need to do it manually.
 Please follow the following guide [to migrate](../migrate_ci_to_ce/README.md) your GitLab CI instance to GitLab CE/EE.
 
-### 10. Start application
+### 10. Use Redis v2.4.0+
+
+Previous versions of GitLab allowed Redis versions >= 2.0 to be used, but
+Sidekiq jobs could fail due to lack of support for the SREM command. GitLab
+8.0 now checks that Redis >= 2.4.0 is used. You can check your Redis version
+with the following command:
+
+    redis-cli info | grep redis_version
+
+### 11. Start application
 
     sudo service gitlab start
     sudo service nginx restart
 
-### 11. Check application status
+### 12. Check application status
 
 Check if GitLab and its environment are configured correctly:
 
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index a66a863f6c45e215c6b9878baa69c3291c1d5c52..da719229ab6854dabac1dfce7deff1fa39b1e3d9 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -23,9 +23,11 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 cd /home/git/gitlab
 sudo -u git -H git fetch --all
 sudo -u git -H git checkout -- Gemfile.lock db/schema.rb
-LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`)
-sudo -u git -H git checkout $LATEST_TAG -b $LATEST_TAG
+sudo -u git -H git checkout LATEST_TAG -b LATEST_TAG
 ```
+Replace `LATEST_TAG` with the latest GitLab tag you want to update to, for example `v8.0.3`.  
+Use `git tag -l 'v*.[0-9]' --sort='v:refname'` to see a list of all tags.  
+Make sure to update patch versions only (check your current version with `cat VERSION`)
 
 ### 3. Update gitlab-shell to the corresponding version
 
diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md
index c185ccfcac31f4a70efd37b108fa825249900b72..ef99a69f60a81bb21e5553cc7bee73cce5ab092a 100644
--- a/doc/web_hooks/web_hooks.md
+++ b/doc/web_hooks/web_hooks.md
@@ -314,7 +314,8 @@ X-Gitlab-Event: Note Hook
         "name": "John Smith",
         "email": "john@example.com"
       }
-    }
+    },
+    "work_in_progress": false
   }
 }
 ```
@@ -500,6 +501,7 @@ X-Gitlab-Event: Merge Request Hook
         "email": "gitlabdev@dv6700.(none)"
       }
     },
+    "work_in_progress": false,
     "url": "http://example.com/diaspora/merge_requests/1",
     "action": "open"
   }
@@ -537,4 +539,4 @@ When you press 'Test Hook' in GitLab, you should see something like this in the
 {"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>}
 example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0
 - -> /
-```
\ No newline at end of file
+```
diff --git a/features/dashboard/new_project.feature b/features/dashboard/new_project.feature
index bbd82a85e3a719b44da8cb24a07e6cc089b8ef29..763920683570d31726b29c602cf5b46c977e5676 100644
--- a/features/dashboard/new_project.feature
+++ b/features/dashboard/new_project.feature
@@ -7,24 +7,24 @@ Background:
   And I click "New project" link
 
   @javascript
-  Scenario: I should see New projects page
-  Then I see "New project" page
+  Scenario: I should see New Projects page
+  Then I see "New Project" page
   Then I see all possible import optios
 
   @javascript
   Scenario: I should see instructions on how to import from Git URL
-  Given I see "New project" page
+  Given I see "New Project" page
   When I click on "Any repo by URL"
   Then I see instructions on how to import from Git URL
 
   @javascript
   Scenario: I should see instructions on how to import from GitHub
-  Given I see "New project" page
+  Given I see "New Project" page
   When I click on "Import project from GitHub"
   Then I see instructions on how to import from GitHub
 
   @javascript
   Scenario: I should see Google Code import page
-  Given I see "New project" page
+  Given I see "New Project" page
   When I click on "Google Code"
   Then I redirected to Google Code import page
diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature
index 34161b81d44cde307683cf64c393f662583ac20a..e4beeb59adc38a3ceb46c7db3d71d631e05090ff 100644
--- a/features/project/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -20,6 +20,8 @@ Feature: Project Commits
     Given commit has ci status
     And I click on commit link
     Then I see commit ci info
+    And I click status link
+    Then I see builds list
 
   Scenario: I browse commit with side-by-side diff view
     Given I click on commit link
diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature
index 58574166ef3e90a5ab6857970aa31d70215c7613..377c5e1a9a7d6390f2e78e9a42df490c1ba8eb10 100644
--- a/features/project/source/browse_files.feature
+++ b/features/project/source/browse_files.feature
@@ -21,12 +21,12 @@ Feature: Project Source Browse Files
     Then I should see raw file content
 
   Scenario: I can create file
-    Given I click on "new file" link in repo
+    Given I click on "New file" link in repo
     Then I can see new file page
 
   @javascript
   Scenario: I can create and commit file
-    Given I click on "new file" link in repo
+    Given I click on "New file" link in repo
     And I edit code
     And I fill the new file name
     And I fill the commit message
@@ -36,14 +36,13 @@ Feature: Project Source Browse Files
 
   @javascript
   Scenario: I can upload file and commit
-    Given I click on "new file" link in repo
-    Then I can see new file page
-    And I can see "upload an existing one"
-    And I click on "upload"
+    Given I click on "Upload file" link in repo
     And I upload a new text file
     And I fill the upload file commit message
+    And I fill the new branch name
     And I click on "Upload file"
     Then I can see the new text file
+    And I am redirected to the uploaded file on new branch
     And I can see the new commit message
 
   @javascript
@@ -59,7 +58,7 @@ Feature: Project Source Browse Files
 
   @javascript
   Scenario: I can create and commit file and specify new branch
-    Given I click on "new file" link in repo
+    Given I click on "New file" link in repo
     And I edit code
     And I fill the new file name
     And I fill the commit message
@@ -83,7 +82,7 @@ Feature: Project Source Browse Files
 
   @javascript
   Scenario: If I enter an illegal file name I see an error message
-    Given I click on "new file" link in repo
+    Given I click on "New file" link in repo
     And I fill the new file name with an illegal name
     And I edit code
     And I fill the commit message
@@ -138,6 +137,24 @@ Feature: Project Source Browse Files
     Then I am on the ".gitignore" edit file page
     And I see a commit error message
 
+  @javascript
+  Scenario: I can create directory in repo
+    When I click on "New directory" link in repo
+    And I fill the new directory name
+    And I fill the commit message
+    And I fill the new branch name
+    And I click on "Create directory"
+    Then I am redirected to the new directory
+
+  @javascript
+  Scenario: I attempt to create an existing directory
+    When I click on "New directory" link in repo
+    And I fill an existing directory name
+    And I fill the commit message
+    And I click on "Create directory"
+    Then I see "Unable to create directory"
+    And I am redirected to the root directory
+
   @javascript
   Scenario: I can see editing preview
     Given I click on ".gitignore" file in repo
diff --git a/features/steps/admin/projects.rb b/features/steps/admin/projects.rb
index 17233f89f38adb2fc2332c1b11e801a4216eca67..5a1cc9aa15145c6f190efef66e92cd6d617f1112 100644
--- a/features/steps/admin/projects.rb
+++ b/features/steps/admin/projects.rb
@@ -41,6 +41,8 @@ class Spinach::Features::AdminProjects < Spinach::FeatureSteps
   end
 
   step 'I transfer project to group \'Web\'' do
+    allow_any_instance_of(Projects::TransferService).
+      to receive(:move_uploads_to_new_namespace).and_return(true)
     find(:xpath, "//input[@id='new_namespace_id']").set group.id
     click_button 'Transfer'
   end
diff --git a/features/steps/dashboard/new_project.rb b/features/steps/dashboard/new_project.rb
index 1e09162a5b513db22c97633c1273f524da9e9c5b..44a4aa9844a239384b943f2f21db51d39f40b3ef 100644
--- a/features/steps/dashboard/new_project.rb
+++ b/features/steps/dashboard/new_project.rb
@@ -3,13 +3,13 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps
   include SharedPaths
   include SharedProject
 
-  step 'I click "New project" link' do
+  step 'I click "New Project" link' do
     page.within('.content') do
-      click_link "New project"
+      click_link "New Project"
     end
   end
 
-  step 'I see "New project" page' do
+  step 'I see "New Project" page' do
     expect(page).to have_content('Project path')
   end
 
diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb
index 5ebc3a49760d7d00da550aabfb8f07aaa75f7524..a3cb83880e30b00de8c88219a71d77632698d981 100644
--- a/features/steps/project/commits/commits.rb
+++ b/features/steps/project/commits/commits.rb
@@ -104,10 +104,20 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
 
   step 'commit has ci status' do
     @project.enable_ci
-    create :ci_commit, gl_project: @project, sha: sample_commit.id
+    ci_commit = create :ci_commit, gl_project: @project, sha: sample_commit.id
+    create :ci_build, commit: ci_commit
   end
 
   step 'I see commit ci info' do
-    expect(page).to have_content "build: skipped"
+    expect(page).to have_content "build: pending"
+  end
+
+  step 'I click status link' do
+    click_link "Builds"
+  end
+
+  step 'I see builds list' do
+    expect(page).to have_content "build: pending"
+    expect(page).to have_content "Latest builds"
   end
 end
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index a1a49dd58a60c3a780ed612dafce054172b6ae48..cb100ca0f549d7dbc878f52a581a6b1812235da8 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -71,7 +71,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I fill the new branch name' do
-    fill_in :new_branch, with: 'new_branch_name'
+    fill_in :new_branch, with: 'new_branch_name', visible: true
   end
 
   step 'I fill the new file name with an illegal name' do
@@ -90,6 +90,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     click_button 'Commit Changes'
   end
 
+  step 'I click on "Create directory"' do
+    click_button 'Create directory'
+  end
+
   step 'I click on "Remove"' do
     click_button 'Remove'
   end
@@ -110,21 +114,32 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     expect(page).to have_css '.line_holder.new'
   end
 
-  step 'I click on "new file" link in repo' do
-    click_link 'new-file-link'
+  step 'I click on "New file" link in repo' do
+    find('.add-to-tree').click
+    click_link 'Create file'
   end
 
-  step 'I can see new file page' do
-    expect(page).to have_content "new file"
-    expect(page).to have_content "Commit message"
+  step 'I click on "Upload file" link in repo' do
+    find('.add-to-tree').click
+    click_link 'Upload file'
+  end
+
+  step 'I click on "New directory" link in repo' do
+    find('.add-to-tree').click
+    click_link 'New directory'
+  end
+
+  step 'I fill the new directory name' do
+    fill_in :dir_name, with: new_dir_name
   end
 
-  step 'I can see "upload an existing one"' do
-    expect(page).to have_content "upload an existing one"
+  step 'I fill an existing directory name' do
+    fill_in :dir_name, with: 'files'
   end
 
-  step 'I click on "upload"' do
-    click_link 'upload'
+  step 'I can see new file page' do
+    expect(page).to have_content "new file"
+    expect(page).to have_content "Commit message"
   end
 
   step 'I click on "Upload file"' do
@@ -228,10 +243,30 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
       @project.namespace, @project, 'new_branch_name/' + new_file_name))
   end
 
+  step 'I am redirected to the uploaded file on new branch' do
+    expect(current_path).to eq(namespace_project_blob_path(
+      @project.namespace, @project,
+      'new_branch_name/' + File.basename(test_text_file)))
+  end
+
+  step 'I am redirected to the new directory' do
+    expect(current_path).to eq(namespace_project_tree_path(
+      @project.namespace, @project, 'new_branch_name/' + new_dir_name))
+  end
+
+  step 'I am redirected to the root directory' do
+    expect(current_path).to eq(namespace_project_tree_path(
+      @project.namespace, @project, 'master/'))
+  end
+
   step "I don't see the permalink link" do
     expect(page).not_to have_link('permalink')
   end
 
+  step 'I see "Unable to create directory"' do
+    expect(page).to have_content('Directory already exists')
+  end
+
   step 'I see a commit error message' do
     expect(page).to have_content('Your changes could not be committed')
   end
@@ -287,6 +322,12 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     'not_a_file.md'
   end
 
+  # Constant value that is a valid directory and
+  # not a directory present at root of the seed repository.
+  def new_dir_name
+    'new_dir/subdir'
+  end
+
   def drop_in_dropzone(file_path)
     # Generate a fake input selector
     page.execute_script <<-JS
diff --git a/lib/api/api.rb b/lib/api/api.rb
index c09488d3547713f815e9c236f18fe36e909b5aa9..afc0402f9e1d3462ba0b800f1171aed3b087dfce 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -46,6 +46,7 @@ module API
     mount Services
     mount Files
     mount Commits
+    mount CommitStatus
     mount Namespaces
     mount Branches
     mount Labels
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2c0596c9dfb64cf730fada8ac4bf16157677294d
--- /dev/null
+++ b/lib/api/commit_statuses.rb
@@ -0,0 +1,80 @@
+require 'mime/types'
+
+module API
+  # Project commit statuses API
+  class CommitStatus < Grape::API
+    resource :projects do
+      before { authenticate! }
+
+      # Get a commit's statuses
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   sha (required) - The commit hash
+      #   ref (optional) - The ref
+      #   stage (optional) - The stage
+      #   name (optional) - The name
+      #   all (optional) - Show all statuses, default: false
+      # Examples:
+      #   GET /projects/:id/repository/commits/:sha/statuses
+      get ':id/repository/commits/:sha/statuses' do
+        authorize! :read_commit_statuses, user_project
+        sha = params[:sha]
+        ci_commit = user_project.ci_commit(sha)
+        not_found! 'Commit' unless ci_commit
+        statuses = ci_commit.statuses
+        statuses = statuses.latest unless parse_boolean(params[:all])
+        statuses = statuses.where(ref: params[:ref]) if params[:ref].present?
+        statuses = statuses.where(stage: params[:stage]) if params[:stage].present?
+        statuses = statuses.where(name: params[:name]) if params[:name].present?
+        present paginate(statuses), with: Entities::CommitStatus
+      end
+
+      # Post status to commit
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   sha (required) - The commit hash
+      #   ref (optional) - The ref
+      #   state (required) - The state of the status. Can be: pending, running, success, error or failure
+      #   target_url (optional) - The target URL to associate with this status
+      #   description (optional) - A short description of the status
+      #   name or context (optional) - A string label to differentiate this status from the status of other systems. Default: "default"
+      # Examples:
+      #   POST /projects/:id/statuses/:sha
+      post ':id/statuses/:sha' do
+        authorize! :create_commit_status, user_project
+        required_attributes! [:state]
+        attrs = attributes_for_keys [:ref, :target_url, :description, :context, :name]
+        commit = @project.commit(params[:sha])
+        not_found! 'Commit' unless commit
+
+        ci_commit = @project.ensure_ci_commit(commit.sha)
+
+        name = params[:name] || params[:context]
+        status = GenericCommitStatus.running_or_pending.find_by(commit: ci_commit, name: name, ref: params[:ref])
+        status ||= GenericCommitStatus.new(commit: ci_commit, user: current_user)
+        status.update(attrs)
+
+        case params[:state].to_s
+        when 'running'
+          status.run
+        when 'success'
+          status.success
+        when 'failed'
+          status.drop
+        when 'canceled'
+          status.cancel
+        else
+          status.status = params[:state].to_s
+        end
+
+        if status.save
+          present status, with: Entities::CommitStatus
+        else
+          render_validation_error!(status)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 9620d36ac4170e459e67ff4458741e1b9fce2fc4..883a5e14b17cea75fc45ed50d82b9fadf7533c19 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -149,6 +149,7 @@ module API
 
     class RepoCommitDetail < RepoCommit
       expose :parent_ids, :committed_date, :authored_date
+      expose :status
     end
 
     class ProjectSnippet < Grape::Entity
@@ -228,6 +229,12 @@ module API
       expose :created_at
     end
 
+    class CommitStatus < Grape::Entity
+      expose :id, :sha, :ref, :status, :name, :target_url, :description,
+             :created_at, :started_at, :finished_at
+      expose :author, using: Entities::UserBasic
+    end
+
     class Event < Grape::Entity
       expose :title, :project_id, :action_name
       expose :target_id, :target_type, :author_id
@@ -255,6 +262,18 @@ module API
       expose :notification_level
     end
 
+    class ProjectService < Grape::Entity
+      expose :id, :title, :created_at, :updated_at, :active
+      expose :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events
+      # Expose serialized properties
+      expose :properties do |service, options|
+        field_names = service.fields.
+          select { |field| options[:include_passwords] || field[:type] != 'password' }.
+          map { |field| field[:name] }
+        service.properties.slice(*field_names)
+      end
+    end
+
     class ProjectWithAccess < Project
       expose :permissions do
         expose :project_access, using: Entities::ProjectAccess do |project, options|
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 63ea2f054386730e65afd4cbe2ec6e2a0afa33aa..f3a59fadf24c12b8581aafa6d3af827c49993317 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -99,7 +99,7 @@ module API
       #   id (required)            - The ID of a project - this will be the source of the merge request
       #   source_branch (required) - The source branch
       #   target_branch (required) - The target branch
-      #   target_project           - The target project of the merge request defaults to the :id of the project
+      #   target_project_id        - The target project of the merge request defaults to the :id of the project
       #   assignee_id              - Assignee user ID
       #   title (required)         - Title of MR
       #   description              - Description of MR
diff --git a/lib/api/services.rb b/lib/api/services.rb
index 6727e80ac1e0f10a0e799a974afaa7d2aa730268..203f04a6259203b46ed4ebca5168c6053c0409d5 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -57,7 +57,7 @@ module API
       #   GET /project/:id/services/gitlab-ci
       #
       get ':id/services/:service_slug' do
-        present project_service
+        present project_service, with: Entities::ProjectService, include_passwords: current_user.is_admin?
       end
     end
   end
diff --git a/lib/ci/api/entities.rb b/lib/ci/api/entities.rb
index f47bc1236b818fdbe14e1a9edb0fe1d03a54f23d..b80c0b8b2735427e5703f2175cb939c03e4b1a26 100644
--- a/lib/ci/api/entities.rb
+++ b/lib/ci/api/entities.rb
@@ -2,7 +2,7 @@ module Ci
   module API
     module Entities
       class Commit < Grape::Entity
-        expose :id, :ref, :sha, :project_id, :before_sha, :created_at
+        expose :id, :sha, :project_id, :created_at
         expose :status, :finished_at, :duration
         expose :git_commit_message, :git_author_name, :git_author_email
       end
@@ -12,7 +12,7 @@ module Ci
       end
 
       class Build < Grape::Entity
-        expose :id, :commands, :ref, :sha, :project_id, :repo_url,
+        expose :id, :commands, :ref, :sha, :status, :project_id, :repo_url,
           :before_sha, :allow_git_fetch, :project_name
 
         expose :options do |model|
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 322aed5e27c33e61b071ae87f6407677619673f5..51e46da82ccd24dd61ff938167bc728518d0820f 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -110,7 +110,7 @@ module ExtractsPath
                                                       @project, @ref, @path)
 
   rescue RuntimeError, NoMethodError, InvalidPathError
-    not_found!
+    render_404
   end
 
   def tree
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index 14ee4701e7bb9faa44e664c9c36124a91efd4305..01b8bda05c6741cf7b914735722447388cec42f7 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -4,7 +4,8 @@ module Gitlab
 
     class KeyAdder < Struct.new(:io)
       def add_key(id, key)
-        io.puts("#{id}\t#{key.strip}")
+        key.gsub!(/[[:space:]]+/, ' ').strip!
+        io.puts("#{id}\t#{key}")
       end
     end
 
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
new file mode 100644
index 0000000000000000000000000000000000000000..741a52714ac98757dfda549a22577fa6e8d6a9b2
--- /dev/null
+++ b/lib/gitlab/database.rb
@@ -0,0 +1,11 @@
+module Gitlab
+  module Database
+    def self.mysql?
+      ActiveRecord::Base.connection.adapter_name.downcase == 'mysql'
+    end
+
+    def self.postgresql?
+      ActiveRecord::Base.connection.adapter_name.downcase == 'postgresql'
+    end
+  end
+end
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index 1ea7751e27dd0b7f9ec0a59e29a202a2972a5718..4be99dd88c29dd87ba829973da60aeca464dbf2d 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -35,7 +35,7 @@ module Gitlab
       end
 
       def find_by_email
-        ::User.find_by(email: auth_hash.email)
+        ::User.find_by(email: auth_hash.email.downcase)
       end
 
       def update_user_attributes
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index ae5f2544691bd7ba415cf2da80cfc6a623351535..32a368c2e2beda201bb63eb4b28251eda26bb390 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -48,6 +48,7 @@ module Gitlab
     autoload :TableOfContentsFilter,        'gitlab/markdown/table_of_contents_filter'
     autoload :TaskListFilter,               'gitlab/markdown/task_list_filter'
     autoload :UserReferenceFilter,          'gitlab/markdown/user_reference_filter'
+    autoload :UploadLinkFilter,             'gitlab/markdown/upload_link_filter'
 
     # Public: Parse the provided text with GitLab-Flavored Markdown
     #
@@ -140,6 +141,7 @@ module Gitlab
         Gitlab::Markdown::SyntaxHighlightFilter,
         Gitlab::Markdown::SanitizationFilter,
 
+        Gitlab::Markdown::UploadLinkFilter,
         Gitlab::Markdown::RelativeLinkFilter,
         Gitlab::Markdown::EmojiFilter,
         Gitlab::Markdown::TableOfContentsFilter,
diff --git a/lib/gitlab/markdown/upload_link_filter.rb b/lib/gitlab/markdown/upload_link_filter.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fbada73ab865c9a677863164f8a1b814839fdf13
--- /dev/null
+++ b/lib/gitlab/markdown/upload_link_filter.rb
@@ -0,0 +1,47 @@
+require 'gitlab/markdown'
+require 'html/pipeline/filter'
+require 'uri'
+
+module Gitlab
+  module Markdown
+    # HTML filter that "fixes" relative upload links to files.
+    # Context options:
+    #   :project (required) - Current project
+    #
+    class UploadLinkFilter < HTML::Pipeline::Filter
+      def call
+        doc.search('a').each do |el|
+          process_link_attr el.attribute('href')
+        end
+
+        doc.search('img').each do |el|
+          process_link_attr el.attribute('src')
+        end
+
+        doc
+      end
+
+      protected
+
+      def process_link_attr(html_attr)
+        return if html_attr.blank?
+
+        uri = html_attr.value
+        if uri.starts_with?("/uploads/")
+          html_attr.value = build_url(uri).to_s
+        end
+      end
+
+      def build_url(uri)
+        File.join(Gitlab.config.gitlab.url, context[:project].path_with_namespace, uri)
+      end
+
+      # Ensure that a :project key exists in context
+      #
+      # Note that while the key might exist, its value could be nil!
+      def validate
+        needs :project
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index 0961bd80421a966bdc575fcce10eaa055ce6ecfe..30497e274c251bb02aa9d53e293e018ba871b5ec 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -39,6 +39,8 @@ module Gitlab
     #
     # Returns the results Array for the requested filter type
     def pipeline_result(filter_type)
+      return [] if @text.blank?
+      
       klass  = filter_type.to_s.camelize + 'ReferenceFilter'
       filter = Gitlab::Markdown.const_get(klass)
 
diff --git a/lib/gitlab/uploads_transfer.rb b/lib/gitlab/uploads_transfer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..be8fcc7b2d256db48600707493f343e198ea4370
--- /dev/null
+++ b/lib/gitlab/uploads_transfer.rb
@@ -0,0 +1,35 @@
+module Gitlab
+  class UploadsTransfer
+    def move_project(project_path, namespace_path_was, namespace_path)
+      new_namespace_folder = File.join(root_dir, namespace_path)
+      FileUtils.mkdir_p(new_namespace_folder) unless Dir.exist?(new_namespace_folder)
+      from = File.join(root_dir, namespace_path_was, project_path)
+      to = File.join(root_dir, namespace_path, project_path)
+      move(from, to, "")
+    end
+
+    def rename_project(path_was, path, namespace_path)
+      base_dir = File.join(root_dir, namespace_path)
+      move(path_was, path, base_dir)
+    end
+
+    def rename_namespace(path_was, path)
+      move(path_was, path)
+    end
+
+    private
+
+    def move(path_was, path, base_dir = nil)
+      base_dir = root_dir unless base_dir
+      from = File.join(base_dir, path_was)
+      to = File.join(base_dir, path)
+      FileUtils.mv(from, to)
+    rescue Errno::ENOENT
+      false
+    end
+
+    def root_dir
+      File.join(Rails.root, "public", "uploads")
+    end
+  end
+end
diff --git a/lib/tasks/gitlab/setup.rake b/lib/tasks/gitlab/setup.rake
index 0ac4b0fa8a36d6cc25bb8ddee696a6a4a747381e..4cbccf2ca897c469aafe0c1f5989f6452922c9a8 100644
--- a/lib/tasks/gitlab/setup.rake
+++ b/lib/tasks/gitlab/setup.rake
@@ -16,6 +16,7 @@ namespace :gitlab do
 
     Rake::Task["db:setup"].invoke
     Rake::Task["add_limits_mysql"].invoke
+    Rake::Task["setup_postgresql"].invoke
     Rake::Task["db:seed_fu"].invoke
   rescue Gitlab::TaskAbortedByUserError
     puts "Quitting...".red
diff --git a/lib/tasks/gitlab/two_factor.rake b/lib/tasks/gitlab/two_factor.rake
new file mode 100644
index 0000000000000000000000000000000000000000..9196677a01769d19df4fb4858f84850312fb0589
--- /dev/null
+++ b/lib/tasks/gitlab/two_factor.rake
@@ -0,0 +1,23 @@
+namespace :gitlab do
+  namespace :two_factor do
+    desc "GitLab | Disable Two-factor authentication (2FA) for all users"
+    task disable_for_all_users: :environment do
+      scope = User.with_two_factor
+      count = scope.count
+
+      if count > 0
+        puts "This will disable 2FA for #{count.to_s.red} users..."
+
+        begin
+          ask_to_continue
+          scope.find_each(&:disable_two_factor!)
+          puts "Successfully disabled 2FA for #{count} users.".green
+        rescue Gitlab::TaskAbortedByUserError
+          puts "Quitting...".red
+        end
+      else
+        puts "There are currently no users with 2FA enabled.".yellow
+      end
+    end
+  end
+end
diff --git a/lib/tasks/migrate/setup_postgresql.rake b/lib/tasks/migrate/setup_postgresql.rake
new file mode 100644
index 0000000000000000000000000000000000000000..bf6894a8351930197172d9a3d2a35ad2ee809ae1
--- /dev/null
+++ b/lib/tasks/migrate/setup_postgresql.rake
@@ -0,0 +1,6 @@
+require Rails.root.join('db/migrate/20151007120511_namespaces_projects_path_lower_indexes')
+
+desc 'GitLab | Sets up PostgreSQL'
+task setup_postgresql: :environment do
+  NamespacesProjectsPathLowerIndexes.new.up
+end
diff --git a/public/robots.txt b/public/robots.txt
index 528f421083e0551c796f0b855fb421e5f5494893..4f616c7f4c1cacff6e93558f47911b883fb5cd76 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -38,7 +38,8 @@ Disallow: /*/*/edit
 Disallow: /*/*/raw
 Disallow: /*/*/blame
 Disallow: /*/*/commits/*/*
-Disallow: /*/*/commit
+Disallow: /*/*/commit/*.patch
+Disallow: /*/*/commit/*.diff
 Disallow: /*/*/compare
 Disallow: /*/*/branches/new
 Disallow: /*/*/tags/new
diff --git a/public/uploads/.gitkeep b/public/uploads/.gitkeep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/spec/benchmarks/finders/trending_projects_finder_spec.rb b/spec/benchmarks/finders/trending_projects_finder_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..551ce21840d6869e8314300f4aa4f2b41a8f7c05
--- /dev/null
+++ b/spec/benchmarks/finders/trending_projects_finder_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe TrendingProjectsFinder, benchmark: true do
+  describe '#execute' do
+    let(:finder) { described_class.new }
+    let(:user)   { create(:user) }
+
+    # to_a is used to force actually running the query (instead of just building
+    # it).
+    benchmark_subject { finder.execute(user).non_archived.to_a }
+
+    it { is_expected.to iterate_per_second(500) }
+  end
+end
diff --git a/spec/benchmarks/models/project_spec.rb b/spec/benchmarks/models/project_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cee0949edc53476ebe3a48d41d68b8bb2b9afd50
--- /dev/null
+++ b/spec/benchmarks/models/project_spec.rb
@@ -0,0 +1,50 @@
+require 'spec_helper'
+
+describe Project, benchmark: true do
+  describe '.trending' do
+    let(:group)    { create(:group) }
+    let(:project1) { create(:empty_project, :public, group: group) }
+    let(:project2) { create(:empty_project, :public, group: group) }
+
+    let(:iterations) { 500 }
+
+    before do
+      2.times do
+        create(:note_on_commit, project: project1)
+      end
+
+      create(:note_on_commit, project: project2)
+    end
+
+    describe 'without an explicit start date' do
+      benchmark_subject { described_class.trending.to_a }
+
+      it { is_expected.to iterate_per_second(iterations) }
+    end
+
+    describe 'with an explicit start date' do
+      let(:date) { 1.month.ago }
+
+      benchmark_subject { described_class.trending(date).to_a }
+
+      it { is_expected.to iterate_per_second(iterations) }
+    end
+  end
+
+  describe '.find_with_namespace' do
+    let(:group)   { create(:group, name: 'sisinmaru') }
+    let(:project) { create(:project, name: 'maru', namespace: group) }
+
+    describe 'using a capitalized namespace' do
+      benchmark_subject { described_class.find_with_namespace('sisinmaru/MARU') }
+
+      it { is_expected.to iterate_per_second(600) }
+    end
+
+    describe 'using a lowercased namespace' do
+      benchmark_subject { described_class.find_with_namespace('sisinmaru/maru') }
+
+      it { is_expected.to iterate_per_second(600) }
+    end
+  end
+end
diff --git a/spec/controllers/ci/commits_controller_spec.rb b/spec/controllers/ci/commits_controller_spec.rb
deleted file mode 100644
index cc39ce7687cebd0b7c2101bc365beadc79aee657..0000000000000000000000000000000000000000
--- a/spec/controllers/ci/commits_controller_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require "spec_helper"
-
-describe Ci::CommitsController do
-  describe "GET /status" do
-    it "returns status of commit" do
-      commit = FactoryGirl.create :ci_commit
-      get :status, id: commit.sha, ref_id: commit.ref, project_id: commit.project.id
-
-      expect(response).to be_success
-      expect(response.code).to eq('200')
-      JSON.parse(response.body)["status"] == "pending"
-    end
-
-    it "returns not_found status" do
-      commit = FactoryGirl.create :ci_commit
-      get :status, id: commit.sha, ref_id: "deploy", project_id: commit.project.id
-
-      expect(response).to be_success
-      expect(response.code).to eq('200')
-      JSON.parse(response.body)["status"] == "not_found"
-    end
-  end
-end
diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb
index 53915856357570e992a65547d3bcc0d6c3ee88d6..a474574c6e5a40284b9a57e9d6ad9ffdd44b81a5 100644
--- a/spec/controllers/projects/tree_controller_spec.rb
+++ b/spec/controllers/projects/tree_controller_spec.rb
@@ -88,4 +88,40 @@ describe Projects::TreeController do
       end
     end
   end
+
+  describe '#create_dir' do
+    render_views
+
+    before do
+      post(:create_dir,
+           namespace_id: project.namespace.to_param,
+           project_id: project.to_param,
+           id: 'master',
+           dir_name: path,
+           new_branch: target_branch,
+           commit_message: 'Test commit message')
+    end
+
+    context 'successful creation' do
+      let(:path) { 'files/new_dir'}
+      let(:target_branch) { 'master-test'}
+
+      it 'redirects to the new directory' do
+        expect(subject).
+            to redirect_to("/#{project.path_with_namespace}/blob/#{target_branch}/#{path}")
+        expect(flash[:notice]).to eq('The directory has been successfully created')
+      end
+    end
+
+    context 'unsuccessful creation' do
+      let(:path) { 'README.md' }
+      let(:target_branch) { 'master'}
+
+      it 'does not allow overwriting of existing files' do
+        expect(subject).
+            to redirect_to("/#{project.path_with_namespace}/blob/master")
+        expect(flash[:alert]).to eq('Directory already exists as a file')
+      end
+    end
+  end
 end
diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb
index f51abfedae529db22d8ec3705233e27e1d0dc61f..93c4494c6607ef084889c7b8faab31158d4bd433 100644
--- a/spec/controllers/projects/uploads_controller_spec.rb
+++ b/spec/controllers/projects/uploads_controller_spec.rb
@@ -33,7 +33,7 @@ describe Projects::UploadsController do
 
       it 'returns a content with original filename, new link, and correct type.' do
         expect(response.body).to match '\"alt\":\"rails_sample\"'
-        expect(response.body).to match "\"url\":\"http://localhost/#{project.path_with_namespace}/uploads"
+        expect(response.body).to match "\"url\":\"/uploads"
         expect(response.body).to match '\"is_image\":true'
       end
     end
@@ -49,7 +49,7 @@ describe Projects::UploadsController do
 
       it 'returns a content with original filename, new link, and correct type.' do
         expect(response.body).to match '\"alt\":\"doc_sample.txt\"'
-        expect(response.body).to match "\"url\":\"http://localhost/#{project.path_with_namespace}/uploads"
+        expect(response.body).to match "\"url\":\"/uploads"
         expect(response.body).to match '\"is_image\":false'
       end
     end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 21b582afba4648b177e0699ff21248a81b67ba6b..2fcd70182b9765414d1fc6c3dd2ab1c2c5ef5de8 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -27,6 +27,7 @@
 
 FactoryGirl.define do
   factory :ci_build, class: Ci::Build do
+    name 'test'
     ref 'master'
     tag false
     started_at 'Di 29. Okt 09:51:28 CET 2013'
diff --git a/spec/factories/commit_statuses.rb b/spec/factories/commit_statuses.rb
new file mode 100644
index 0000000000000000000000000000000000000000..52de437052d99e4047900e64560c5771a06afb13
--- /dev/null
+++ b/spec/factories/commit_statuses.rb
@@ -0,0 +1,15 @@
+FactoryGirl.define do
+  factory :commit_status, class: CommitStatus do
+    started_at 'Di 29. Okt 09:51:28 CET 2013'
+    finished_at 'Di 29. Okt 09:53:28 CET 2013'
+    name 'default'
+    status 'success'
+    description 'commit status'
+    commit factory: :ci_commit
+
+    factory :generic_commit_status, class: GenericCommitStatus do
+      name 'generic'
+      description 'external commit status'
+    end
+  end
+end
diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..924047a0d8fafd2d49d0a73f7bf6c1af973bfbd6
--- /dev/null
+++ b/spec/features/builds_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe "Builds" do
+  before do
+    login_as(:user)
+    @commit = FactoryGirl.create :ci_commit
+    @build = FactoryGirl.create :ci_build, commit: @commit
+    @gl_project = @commit.project.gl_project
+    @gl_project.team << [@user, :master]
+  end
+
+  describe "GET /:project/builds/:id" do
+    before do
+      visit namespace_project_build_path(@gl_project.namespace, @gl_project, @build)
+    end
+
+    it { expect(page).to have_content @commit.sha[0..7] }
+    it { expect(page).to have_content @commit.git_commit_message }
+    it { expect(page).to have_content @commit.git_author_name }
+  end
+
+  describe "GET /:project/builds/:id/cancel" do
+    before do
+      @build.run!
+      visit cancel_namespace_project_build_path(@gl_project.namespace, @gl_project, @build)
+    end
+
+    it { expect(page).to have_content 'canceled' }
+    it { expect(page).to have_content 'Retry' }
+  end
+
+  describe "POST /:project/builds/:id/retry" do
+    before do
+      visit cancel_namespace_project_build_path(@gl_project.namespace, @gl_project, @build)
+      click_link 'Retry'
+    end
+
+    it { expect(page).to have_content 'pending' }
+    it { expect(page).to have_content 'Cancel' }
+  end
+end
diff --git a/spec/features/ci/builds_spec.rb b/spec/features/ci/builds_spec.rb
deleted file mode 100644
index d65699dbefa7319b2959fcb3fd72e5736578f591..0000000000000000000000000000000000000000
--- a/spec/features/ci/builds_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'spec_helper'
-
-describe "Builds" do
-  context :private_project do
-    before do
-      @commit = FactoryGirl.create :ci_commit
-      @build = FactoryGirl.create :ci_build, commit: @commit
-      login_as :user
-      @commit.project.gl_project.team << [@user, :master]
-    end
-
-    describe "GET /:project/builds/:id" do
-      before do
-        visit ci_project_build_path(@commit.project, @build)
-      end
-
-      it { expect(page).to have_content @commit.sha[0..7] }
-      it { expect(page).to have_content @commit.git_commit_message }
-      it { expect(page).to have_content @commit.git_author_name }
-    end
-
-    describe "GET /:project/builds/:id/cancel" do
-      before do
-        @build.run!
-        visit cancel_ci_project_build_path(@commit.project, @build)
-      end
-
-      it { expect(page).to have_content 'canceled' }
-      it { expect(page).to have_content 'Retry' }
-    end
-
-    describe "POST /:project/builds/:id/retry" do
-      before do
-        @build.cancel!
-        visit ci_project_build_path(@commit.project, @build)
-        click_link 'Retry'
-      end
-
-      it { expect(page).to have_content 'pending' }
-      it { expect(page).to have_content 'Cancel' }
-    end
-  end
-
-  context :public_project do
-    describe "Show page public accessible" do
-      before do
-        @commit = FactoryGirl.create :ci_commit
-        @commit.project.public = true
-        @commit.project.save
-        
-        @runner = FactoryGirl.create :ci_specific_runner
-        @build = FactoryGirl.create :ci_build, commit: @commit, runner: @runner
-
-        stub_gitlab_calls
-        visit ci_project_build_path(@commit.project, @build)
-      end
-
-      it { expect(page).to have_content @commit.sha[0..7] }
-    end
-  end
-end
diff --git a/spec/features/ci/projects_spec.rb b/spec/features/ci/projects_spec.rb
deleted file mode 100644
index c633acf85fbf478c6d91047090d4e7154298f747..0000000000000000000000000000000000000000
--- a/spec/features/ci/projects_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'spec_helper'
-
-describe "Projects" do
-  let(:user)    { create(:user) }
-
-  before do
-    login_as(user)
-    @project = FactoryGirl.create :ci_project, name: "GitLab / gitlab-shell"
-    @project.gl_project.team << [user, :master]
-  end
-
-  describe "GET /ci/projects/:id" do
-    before do
-      visit ci_project_path(@project)
-    end
-
-    it { expect(page).to have_content @project.name }
-    it { expect(page).to have_content 'All commits' }
-  end
-end
diff --git a/spec/features/ci/commits_spec.rb b/spec/features/commits_spec.rb
similarity index 52%
rename from spec/features/ci/commits_spec.rb
rename to spec/features/commits_spec.rb
index b4236e1e589626bdf4cf95da32abcaff359c6627..1adc2cdf70a235bfaab9d1b8b3433c033ef077d3 100644
--- a/spec/features/ci/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -1,14 +1,18 @@
 require 'spec_helper'
 
 describe "Commits" do
-  include Ci::CommitsHelper
+  include CiStatusHelper
 
-  context "Authenticated user" do
+  let(:project) { create(:project) }
+
+  describe "CI" do
     before do
-      @commit = FactoryGirl.create :ci_commit
-      @build = FactoryGirl.create :ci_build, commit: @commit
       login_as :user
-      @commit.project.gl_project.team << [@user, :master]
+      project.team << [@user, :master]
+      @ci_project = project.ensure_gitlab_ci_project
+      @commit = FactoryGirl.create :ci_commit, gl_project: project, sha: project.commit.sha
+      @build = FactoryGirl.create :ci_build, commit: @commit
+      @generic_status = FactoryGirl.create :generic_commit_status, commit: @commit
     end
 
     before do
@@ -17,7 +21,7 @@ describe "Commits" do
 
     describe "GET /:project/commits/:sha" do
       before do
-        visit ci_commit_path(@commit)
+        visit ci_status_path(@commit)
       end
 
       it { expect(page).to have_content @commit.sha[0..7] }
@@ -25,49 +29,33 @@ describe "Commits" do
       it { expect(page).to have_content @commit.git_author_name }
     end
 
-    describe "Cancel commit" do
+    describe "Cancel all builds" do
       it "cancels commit" do
-        visit ci_commit_path(@commit)
-        click_on "Cancel"
+        visit ci_status_path(@commit)
+        click_on "Cancel all"
+        expect(page).to have_content "canceled"
+      end
+    end
 
+    describe "Cancel build" do
+      it "cancels build" do
+        visit ci_status_path(@commit)
+        click_on "Cancel"
         expect(page).to have_content "canceled"
       end
     end
 
     describe ".gitlab-ci.yml not found warning" do
       it "does not show warning" do
-        visit ci_commit_path(@commit)
-
+        visit ci_status_path(@commit)
         expect(page).not_to have_content ".gitlab-ci.yml not found in this commit"
       end
 
       it "shows warning" do
         stub_ci_commit_yaml_file(nil)
-
-        visit ci_commit_path(@commit)
-
+        visit ci_status_path(@commit)
         expect(page).to have_content ".gitlab-ci.yml not found in this commit"
       end
     end
   end
-
-  context "Public pages" do
-    before do
-      @commit = FactoryGirl.create :ci_commit
-      @commit.project.public = true
-      @commit.project.save
-
-      @build = FactoryGirl.create :ci_build, commit: @commit
-    end
-
-    describe "GET /:project/commits/:sha" do
-      before do
-        visit ci_commit_path(@commit)
-      end
-
-      it { expect(page).to have_content @commit.sha[0..7] }
-      it { expect(page).to have_content @commit.git_commit_message }
-      it { expect(page).to have_content @commit.git_author_name }
-    end
-  end
 end
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index a362c54b9ad5ac7aa95fe40bd227bdc23230a791..aac93b17a3800dee846bd33ca872f85cb3621f0a 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -50,7 +50,7 @@ feature 'Project', feature: true do
   end
 
   def remove_project
-    click_link "Remove project"
+    click_button "Remove project"
     fill_in 'confirm_name_input', with: project.path
     click_button 'Confirm'
   end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index db20b23f87d55b62909ff9859b75e270b58e4e95..b16480554622bf064284ce14688d2083a72332c3 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -6,9 +6,11 @@ describe IssuesFinder do
   let(:project1) { create(:project) }
   let(:project2) { create(:project) }
   let(:milestone) { create(:milestone, project: project1) }
+  let(:label) { create(:label, project: project2) }
   let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone) }
   let(:issue2) { create(:issue, author: user, assignee: user, project: project2) }
   let(:issue3) { create(:issue, author: user2, assignee: user2, project: project2) }
+  let!(:label_link) { create(:label_link, label: label, target: issue2) }
 
   before do
     project1.team << [user, :master]
@@ -48,6 +50,24 @@ describe IssuesFinder do
         expect(issues).to eq([issue1])
       end
 
+      it 'should filter by no milestone id' do
+        params = { scope: "all", milestone_title: Milestone::None.title, state: 'opened' }
+        issues = IssuesFinder.new(user, params).execute
+        expect(issues).to match_array([issue2, issue3])
+      end
+
+      it 'should filter by label name' do
+        params = { scope: "all", label_name: label.title, state: 'opened' }
+        issues = IssuesFinder.new(user, params).execute
+        expect(issues).to eq([issue2])
+      end
+
+      it 'should filter by no label name' do
+        params = { scope: "all", label_name: Label::None.title, state: 'opened' }
+        issues = IssuesFinder.new(user, params).execute
+        expect(issues).to match_array([issue1, issue3])
+      end
+
       it 'should be empty for unauthorized user' do
         params = { scope: "all", state: 'opened' }
         issues = IssuesFinder.new(nil, params).execute
diff --git a/spec/finders/trending_projects_finder_spec.rb b/spec/finders/trending_projects_finder_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a49cbfd5160194614615fa7c9df99a5bc701c6d3
--- /dev/null
+++ b/spec/finders/trending_projects_finder_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe TrendingProjectsFinder do
+  let(:user) { build(:user) }
+
+  describe '#execute' do
+    describe 'without an explicit start date' do
+      subject { described_class.new }
+
+      it 'returns the trending projects' do
+        relation = double(:ar_relation)
+
+        allow(subject).to receive(:projects_for)
+          .with(user)
+          .and_return(relation)
+
+        allow(relation).to receive(:trending)
+          .with(an_instance_of(ActiveSupport::TimeWithZone))
+      end
+    end
+
+    describe 'with an explicit start date' do
+      let(:date) { 2.months.ago }
+
+      subject { described_class.new }
+
+      it 'returns the trending projects' do
+        relation = double(:ar_relation)
+
+        allow(subject).to receive(:projects_for)
+          .with(user)
+          .and_return(relation)
+
+        allow(relation).to receive(:trending)
+          .with(date)
+      end
+    end
+  end
+end
diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb
index 0c8d06b7059bed24926fad705e09c5d8a3299049..fb70a36dc02f84078badbf26d0ae618d8a3178fc 100644
--- a/spec/helpers/labels_helper_spec.rb
+++ b/spec/helpers/labels_helper_spec.rb
@@ -14,6 +14,11 @@ describe LabelsHelper do
         expect(label).not_to receive(:project)
         link_to_label(label)
       end
+
+      it 'includes option for "No Label"' do
+        result = project_labels_options(project)
+        expect(result).to include('No Label')
+      end
     end
 
     context 'without @project set' do
diff --git a/spec/helpers/runners_helper_spec.rb b/spec/helpers/runners_helper_spec.rb
index b3d635a193274b56013d00e377e57516474cf404..35f91b7decfde61701c8567d40bcf2fba7499a98 100644
--- a/spec/helpers/runners_helper_spec.rb
+++ b/spec/helpers/runners_helper_spec.rb
@@ -12,7 +12,7 @@ describe RunnersHelper do
   end
 
   it "returns online text" do
-    runner = FactoryGirl.build(:ci_runner, contacted_at: 1.hour.ago, active: true)
+    runner = FactoryGirl.build(:ci_runner, contacted_at: 1.second.ago, active: true)
     expect(runner_status_icon(runner)).to include("Runner is online")
   end
 end
diff --git a/spec/javascripts/behaviors/quick_submit_spec.js.coffee b/spec/javascripts/behaviors/quick_submit_spec.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..09708c12ed43b535c4f1d91dfb212a4461cdc93b
--- /dev/null
+++ b/spec/javascripts/behaviors/quick_submit_spec.js.coffee
@@ -0,0 +1,70 @@
+#= require behaviors/quick_submit
+
+describe 'Quick Submit behavior', ->
+  fixture.preload('behaviors/quick_submit.html')
+
+  beforeEach ->
+    fixture.load('behaviors/quick_submit.html')
+
+    # Prevent a form submit from moving us off the testing page
+    $('form').submit (e) -> e.preventDefault()
+
+    @spies = {
+      submit: spyOnEvent('form', 'submit')
+    }
+
+  it 'does not respond to other keyCodes', ->
+    $('input').trigger(keydownEvent(keyCode: 32))
+
+    expect(@spies.submit).not.toHaveBeenTriggered()
+
+  it 'does not respond to Enter alone', ->
+    $('input').trigger(keydownEvent(ctrlKey: false, metaKey: false))
+
+    expect(@spies.submit).not.toHaveBeenTriggered()
+
+  it 'does not respond to repeated events', ->
+    $('input').trigger(keydownEvent(repeat: true))
+
+    expect(@spies.submit).not.toHaveBeenTriggered()
+
+  it 'disables submit buttons', ->
+    $('textarea').trigger(keydownEvent())
+
+    expect($('input[type=submit]')).toBeDisabled()
+    expect($('button[type=submit]')).toBeDisabled()
+
+  # We cannot stub `navigator.userAgent` for CI's `rake teaspoon` task, so we'll
+  # only run the tests that apply to the current platform
+  if navigator.userAgent.match(/Macintosh/)
+    it 'responds to Meta+Enter', ->
+      $('input').trigger(keydownEvent())
+
+      expect(@spies.submit).toHaveBeenTriggered()
+
+    it 'excludes other modifier keys', ->
+      $('input').trigger(keydownEvent(altKey: true))
+      $('input').trigger(keydownEvent(ctrlKey: true))
+      $('input').trigger(keydownEvent(shiftKey: true))
+
+      expect(@spies.submit).not.toHaveBeenTriggered()
+  else
+    it 'responds to Ctrl+Enter', ->
+      $('input').trigger(keydownEvent())
+
+      expect(@spies.submit).toHaveBeenTriggered()
+
+    it 'excludes other modifier keys', ->
+      $('input').trigger(keydownEvent(altKey: true))
+      $('input').trigger(keydownEvent(metaKey: true))
+      $('input').trigger(keydownEvent(shiftKey: true))
+
+      expect(@spies.submit).not.toHaveBeenTriggered()
+
+  keydownEvent = (options) ->
+    if navigator.userAgent.match(/Macintosh/)
+      defaults = { keyCode: 13, metaKey: true }
+    else
+      defaults = { keyCode: 13, ctrlKey: true }
+
+    $.Event('keydown', $.extend({}, defaults, options))
diff --git a/spec/javascripts/fixtures/behaviors/quick_submit.html.haml b/spec/javascripts/fixtures/behaviors/quick_submit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b80a28a33ea82eac1a0345c76f424ea2dcf2db48
--- /dev/null
+++ b/spec/javascripts/fixtures/behaviors/quick_submit.html.haml
@@ -0,0 +1,6 @@
+%form{ action: '/foo' }
+  %input.js-quick-submit{ type: 'text' }
+  %textarea.js-quick-submit
+
+  %input{ type: 'submit'} Submit
+  %button.btn{ type: 'submit' } Submit
diff --git a/spec/javascripts/fixtures/line_highlighter.html.haml b/spec/javascripts/fixtures/line_highlighter.html.haml
index da1ebcdb23cacb744c7824b612e5c496f15ce086..514877340e4f2ba38b55037cc92318798c0c003e 100644
--- a/spec/javascripts/fixtures/line_highlighter.html.haml
+++ b/spec/javascripts/fixtures/line_highlighter.html.haml
@@ -1,4 +1,4 @@
-#tree-content-holder
+#blob-content-holder
   .file-content
     .line-numbers
       - 1.upto(25) do |i|
diff --git a/spec/javascripts/line_highlighter_spec.js.coffee b/spec/javascripts/line_highlighter_spec.js.coffee
index 57453c716a5df44f2e7df4268beab377a993d9fb..a073f21e7bcbe563f53bab788be747dbf9fea754 100644
--- a/spec/javascripts/line_highlighter_spec.js.coffee
+++ b/spec/javascripts/line_highlighter_spec.js.coffee
@@ -39,7 +39,7 @@ describe 'LineHighlighter', ->
       expect(spy).toHaveBeenPrevented()
 
     it 'handles garbage input from the hash', ->
-      func = -> new LineHighlighter('#tree-content-holder')
+      func = -> new LineHighlighter('#blob-content-holder')
       expect(func).not.toThrow()
 
   describe '#clickHandler', ->
diff --git a/spec/javascripts/spec_helper.coffee b/spec/javascripts/spec_helper.coffee
index 47b41dd2c8161025053acf709cedf1e00ec7579b..90b02a6aec59b150f5347b28ce1683693a36f08a 100644
--- a/spec/javascripts/spec_helper.coffee
+++ b/spec/javascripts/spec_helper.coffee
@@ -9,6 +9,7 @@
 # require the specific files that are being used in the spec that tests them.
 
 #= require jquery
+#= require jquery.turbolinks
 #= require bootstrap
 #= require underscore
 
diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb
index b6d04330599bd2988f13e0e06f828418fc8f7f07..b60e23454d60f875ca722fca949fd1c228e98ccf 100644
--- a/spec/lib/gitlab/backend/shell_spec.rb
+++ b/spec/lib/gitlab/backend/shell_spec.rb
@@ -15,4 +15,17 @@ describe Gitlab::Shell do
   it { is_expected.to respond_to :fork_repository }
 
   it { expect(gitlab_shell.url_to_repo('diaspora')).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git") }
+
+  describe Gitlab::Shell::KeyAdder do
+    describe '#add_key' do
+      it 'normalizes space characters in the key' do
+        io = spy
+        adder = described_class.new(io)
+
+        adder.add_key('key-42', "sha-rsa foo\tbar\tbaz")
+
+        expect(io).to have_received(:puts).with("key-42\tsha-rsa foo bar baz")
+      end
+    end
+  end
 end
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7cdebdf209aa540ba73e8f075491e20518167680
--- /dev/null
+++ b/spec/lib/gitlab/database_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe Gitlab::Database do
+  # These are just simple smoke tests to check if the methods work (regardless
+  # of what they may return).
+  describe '.mysql?' do
+    subject { described_class.mysql? }
+
+    it { is_expected.to satisfy { |val| val == true || val == false } }
+  end
+
+  describe '.postgresql?' do
+    subject { described_class.postgresql? }
+
+    it { is_expected.to satisfy { |val| val == true || val == false } }
+  end
+end
diff --git a/spec/lib/gitlab/email/attachment_uploader_spec.rb b/spec/lib/gitlab/email/attachment_uploader_spec.rb
index e8208e15e29ead60bb92b74ea82da81661dc40bf..8fb432367b63ddc603ca6b128f88537c7d6b9c7b 100644
--- a/spec/lib/gitlab/email/attachment_uploader_spec.rb
+++ b/spec/lib/gitlab/email/attachment_uploader_spec.rb
@@ -13,7 +13,6 @@ describe Gitlab::Email::AttachmentUploader do
       expect(link).not_to be_nil
       expect(link[:is_image]).to be_truthy
       expect(link[:alt]).to eq("bricks")
-      expect(link[:url]).to include("/#{project.path_with_namespace}")
       expect(link[:url]).to include("bricks.png")
     end
   end
diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb
index fd2e5f6d0e170df0dc56f347b2f99d61fb3b04e6..b5b56a349526774d7f5dd98194a4e1d7092d3844 100644
--- a/spec/lib/gitlab/ldap/user_spec.rb
+++ b/spec/lib/gitlab/ldap/user_spec.rb
@@ -13,6 +13,17 @@ describe Gitlab::LDAP::User do
   let(:auth_hash) do
     OmniAuth::AuthHash.new(uid: 'my-uid', provider: 'ldapmain', info: info)
   end
+  let(:ldap_user_upper_case) { Gitlab::LDAP::User.new(auth_hash_upper_case) }
+  let(:info_upper_case) do
+    {
+      name: 'John',
+      email: 'John@Example.com', # Email address has upper case chars
+      nickname: 'john'
+    }
+  end
+  let(:auth_hash_upper_case) do
+    OmniAuth::AuthHash.new(uid: 'my-uid', provider: 'ldapmain', info: info_upper_case)
+  end
 
   describe :changed? do
     it "marks existing ldap user as changed" do
@@ -57,6 +68,16 @@ describe Gitlab::LDAP::User do
       expect(existing_user.id).to eql ldap_user.gl_user.id
     end
 
+    it 'connects to existing ldap user if the extern_uid changes and email address has upper case characters' do
+      existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'old-uid', provider: 'ldapmain')
+      expect{ ldap_user_upper_case.save }.not_to change{ User.count }
+
+      existing_user.reload
+      expect(existing_user.ldap_identity.extern_uid).to eql 'my-uid'
+      expect(existing_user.ldap_identity.provider).to eql 'ldapmain'
+      expect(existing_user.id).to eql ldap_user.gl_user.id
+    end
+
     it 'maintains an identity per provider' do
       existing_user = create(:omniauth_user, email: 'john@example.com', provider: 'twitter')
       expect(existing_user.identities.count).to eql(1)
diff --git a/spec/lib/gitlab/markdown/upload_link_filter_spec.rb b/spec/lib/gitlab/markdown/upload_link_filter_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9ae45a6f5597e035e11e393b5424f34fca221ce9
--- /dev/null
+++ b/spec/lib/gitlab/markdown/upload_link_filter_spec.rb
@@ -0,0 +1,75 @@
+# encoding: UTF-8
+
+require 'spec_helper'
+
+module Gitlab::Markdown
+  describe UploadLinkFilter do
+    def filter(doc, contexts = {})
+      contexts.reverse_merge!({
+        project: project
+      })
+
+      described_class.call(doc, contexts)
+    end
+
+    def image(path)
+      %(<img src="#{path}" />)
+    end
+
+    def link(path)
+      %(<a href="#{path}">#{path}</a>)
+    end
+
+    let(:project) { create(:project) }
+
+    shared_examples :preserve_unchanged do
+      it 'does not modify any relative URL in anchor' do
+        doc = filter(link('README.md'))
+        expect(doc.at_css('a')['href']).to eq 'README.md'
+      end
+
+      it 'does not modify any relative URL in image' do
+        doc = filter(image('files/images/logo-black.png'))
+        expect(doc.at_css('img')['src']).to eq 'files/images/logo-black.png'
+      end
+    end
+
+    it 'does not raise an exception on invalid URIs' do
+      act = link("://foo")
+      expect { filter(act) }.not_to raise_error
+    end
+
+    context 'with a valid repository' do
+      it 'rebuilds relative URL for a link' do
+        doc = filter(link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg'))
+        expect(doc.at_css('a')['href']).
+          to eq "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg"
+      end
+
+      it 'rebuilds relative URL for an image' do
+        doc = filter(link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg'))
+        expect(doc.at_css('a')['href']).
+          to eq "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg"
+      end
+
+      it 'does not modify absolute URL' do
+        doc = filter(link('http://example.com'))
+        expect(doc.at_css('a')['href']).to eq 'http://example.com'
+      end
+
+      it 'supports Unicode filenames' do
+        path = '/uploads/한글.png'
+        escaped = Addressable::URI.escape(path)
+
+        # Stub these methods so the file doesn't actually need to be in the repo
+        allow_any_instance_of(described_class).
+          to receive(:file_exists?).and_return(true)
+        allow_any_instance_of(described_class).
+          to receive(:image?).with(path).and_return(true)
+
+        doc = filter(image(escaped))
+        expect(doc.at_css('img')['src']).to match "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/%ED%95%9C%EA%B8%80.png"
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/uploads_transfer_spec.rb b/spec/lib/gitlab/uploads_transfer_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..260364a513e4d2646213999645cd09511ba0b85d
--- /dev/null
+++ b/spec/lib/gitlab/uploads_transfer_spec.rb
@@ -0,0 +1,50 @@
+require 'spec_helper'
+
+describe Gitlab::UploadsTransfer do
+  before do
+    @root_dir = File.join(Rails.root, "public", "uploads")
+    @upload_transfer = Gitlab::UploadsTransfer.new
+
+    @project_path_was = "test_project_was"
+    @project_path = "test_project"
+    @namespace_path_was = "test_namespace_was"
+    @namespace_path = "test_namespace"
+  end
+
+  after do
+    FileUtils.rm_rf([
+      File.join(@root_dir, @namespace_path),
+      File.join(@root_dir, @namespace_path_was)
+    ])
+  end
+
+  describe '#move_project' do
+    it "moves project upload to another namespace" do
+      FileUtils.mkdir_p(File.join(@root_dir, @namespace_path_was, @project_path))
+      @upload_transfer.move_project(@project_path, @namespace_path_was, @namespace_path)
+
+      expected_path = File.join(@root_dir, @namespace_path, @project_path)
+      expect(Dir.exist?(expected_path)).to be_truthy
+    end
+  end
+
+  describe '#rename_project' do
+    it "renames project" do
+      FileUtils.mkdir_p(File.join(@root_dir, @namespace_path, @project_path_was))
+      @upload_transfer.rename_project(@project_path_was, @project_path, @namespace_path)
+
+      expected_path = File.join(@root_dir, @namespace_path, @project_path)
+      expect(Dir.exist?(expected_path)).to be_truthy
+    end
+  end
+
+  describe '#rename_namespace' do
+    it "renames namespace" do
+      FileUtils.mkdir_p(File.join(@root_dir, @namespace_path_was, @project_path))
+      @upload_transfer.rename_namespace(@namespace_path_was, @namespace_path)
+
+      expected_path = File.join(@root_dir, @namespace_path, @project_path)
+      expect(Dir.exist?(expected_path)).to be_truthy
+    end
+  end
+end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/build_spec.rb
similarity index 70%
rename from spec/models/ci/build_spec.rb
rename to spec/models/build_spec.rb
index da56f6e31ae11673498d682be19e8903c8881735..7f5abb83ac2298813e596c95468be60fc16dbfc8 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/build_spec.rb
@@ -30,17 +30,9 @@ describe Ci::Build do
   let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project }
   let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project }
   let(:build) { FactoryGirl.create :ci_build, commit: commit }
-  subject { build }
 
-  it { is_expected.to belong_to(:commit) }
-  it { is_expected.to belong_to(:user) }
-  it { is_expected.to validate_presence_of :status }
   it { is_expected.to validate_presence_of :ref }
 
-  it { is_expected.to respond_to :success? }
-  it { is_expected.to respond_to :failed? }
-  it { is_expected.to respond_to :running? }
-  it { is_expected.to respond_to :pending? }
   it { is_expected.to respond_to :trace_html }
 
   describe :first_pending do
@@ -67,72 +59,6 @@ describe Ci::Build do
     end
   end
 
-  describe :started? do
-    subject { build.started? }
-
-    context 'without started_at' do
-      before { build.started_at = nil }
-
-      it { is_expected.to be_falsey }
-    end
-
-    %w(running success failed).each do |status|
-      context "if build status is #{status}" do
-        before { build.status = status }
-
-        it { is_expected.to be_truthy }
-      end
-    end
-
-    %w(pending canceled).each do |status|
-      context "if build status is #{status}" do
-        before { build.status = status }
-
-        it { is_expected.to be_falsey }
-      end
-    end
-  end
-
-  describe :active? do
-    subject { build.active? }
-
-    %w(pending running).each do |state|
-      context "if build.status is #{state}" do
-        before { build.status = state }
-
-        it { is_expected.to be_truthy }
-      end
-    end
-
-    %w(success failed canceled).each do |state|
-      context "if build.status is #{state}" do
-        before { build.status = state }
-
-        it { is_expected.to be_falsey }
-      end
-    end
-  end
-
-  describe :complete? do
-    subject { build.complete? }
-
-    %w(success failed canceled).each do |state|
-      context "if build.status is #{state}" do
-        before { build.status = state }
-
-        it { is_expected.to be_truthy }
-      end
-    end
-
-    %w(pending running).each do |state|
-      context "if build.status is #{state}" do
-        before { build.status = state }
-
-        it { is_expected.to be_falsey }
-      end
-    end
-  end
-
   describe :ignored? do
     subject { build.ignored? }
 
@@ -200,31 +126,6 @@ describe Ci::Build do
     it { is_expected.to eq(commit.project.timeout) }
   end
 
-  describe :duration do
-    subject { build.duration }
-
-    it { is_expected.to eq(120.0) }
-
-    context 'if the building process has not started yet' do
-      before do
-        build.started_at = nil
-        build.finished_at = nil
-      end
-
-      it { is_expected.to be_nil }
-    end
-
-    context 'if the building process has started' do
-      before do
-        build.started_at = Time.now - 1.minute
-        build.finished_at = nil
-      end
-
-      it { is_expected.to be_a(Float) }
-      it { is_expected.to be > 0.0 }
-    end
-  end
-
   describe :options do
     let(:options) do
       {
@@ -239,18 +140,6 @@ describe Ci::Build do
     it { is_expected.to eq(options) }
   end
 
-  describe :sha do
-    subject { build.sha }
-
-    it { is_expected.to eq(commit.sha) }
-  end
-
-  describe :short_sha do
-    subject { build.short_sha }
-
-    it { is_expected.to eq(commit.short_sha) }
-  end
-
   describe :allow_git_fetch do
     subject { build.allow_git_fetch }
 
@@ -311,13 +200,34 @@ describe Ci::Build do
     context 'returns variables' do
       subject { build.variables }
 
-      let(:variables) do
+      let(:predefined_variables) do
+        [
+          { key: :CI_BUILD_NAME, value: 'test', public: true },
+          { key: :CI_BUILD_STAGE, value: 'stage', public: true },
+        ]
+      end
+
+      let(:yaml_variables) do
         [
           { key: :DB_NAME, value: 'postgres', public: true }
         ]
       end
 
-      it { is_expected.to eq(variables) }
+      before { build.update_attributes(stage: 'stage') }
+
+      it { is_expected.to eq(predefined_variables + yaml_variables) }
+
+      context 'for tag' do
+        let(:tag_variable) do
+          [
+            { key: :CI_BUILD_TAG, value: 'master', public: true }
+          ]
+        end
+
+        before { build.update_attributes(tag: true) }
+
+        it { is_expected.to eq(tag_variable + predefined_variables + yaml_variables) }
+      end
 
       context 'and secure variables' do
         let(:secure_variables) do
@@ -330,7 +240,7 @@ describe Ci::Build do
           build.project.variables << Ci::Variable.new(key: 'SECRET_KEY', value: 'secret_value')
         end
 
-        it { is_expected.to eq(variables + secure_variables) }
+        it { is_expected.to eq(predefined_variables + yaml_variables + secure_variables) }
 
         context 'and trigger variables' do
           let(:trigger) { FactoryGirl.create :ci_trigger, project: project }
@@ -340,12 +250,17 @@ describe Ci::Build do
               { key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false }
             ]
           end
+          let(:predefined_trigger_variable) do
+            [
+              { key: :CI_BUILD_TRIGGERED, value: 'true', public: true }
+            ]
+          end
 
           before do
             build.trigger_request = trigger_request
           end
 
-          it { is_expected.to eq(variables + secure_variables + trigger_variables) }
+          it { is_expected.to eq(predefined_variables + predefined_trigger_variable + yaml_variables + secure_variables + trigger_variables) }
         end
       end
     end
@@ -384,4 +299,105 @@ describe Ci::Build do
       is_expected.to eq(['rec1', pusher_email])
     end
   end
+
+  describe :can_be_served? do
+    let(:runner) { FactoryGirl.create :ci_specific_runner }
+
+    before { build.project.runners << runner }
+
+    context 'runner without tags' do
+      it 'can handle builds without tags' do
+        expect(build.can_be_served?(runner)).to be_truthy
+      end
+
+      it 'cannot handle build with tags' do
+        build.tag_list = ['aa']
+        expect(build.can_be_served?(runner)).to be_falsey
+      end
+    end
+
+    context 'runner with tags' do
+      before { runner.tag_list = ['bb', 'cc'] }
+
+      it 'can handle builds without tags' do
+        expect(build.can_be_served?(runner)).to be_truthy
+      end
+
+      it 'can handle build with matching tags' do
+        build.tag_list = ['bb']
+        expect(build.can_be_served?(runner)).to be_truthy
+      end
+
+      it 'cannot handle build with not matching tags' do
+        build.tag_list = ['aa']
+        expect(build.can_be_served?(runner)).to be_falsey
+      end
+    end
+  end
+
+  describe :any_runners_online? do
+    subject { build.any_runners_online? }
+
+    context 'when no runners' do
+      it { is_expected.to be_falsey }
+    end
+
+    context 'if there are runner' do
+      let(:runner) { FactoryGirl.create :ci_specific_runner }
+
+      before do
+        build.project.runners << runner
+        runner.update_attributes(contacted_at: 1.second.ago)
+      end
+
+      it { is_expected.to be_truthy }
+
+      it 'that is inactive' do
+        runner.update_attributes(active: false)
+        is_expected.to be_falsey
+      end
+
+      it 'that is not online' do
+        runner.update_attributes(contacted_at: nil)
+        is_expected.to be_falsey
+      end
+
+      it 'that cannot handle build' do
+        expect_any_instance_of(Ci::Build).to receive(:can_be_served?).and_return(false)
+        is_expected.to be_falsey
+      end
+
+    end
+  end
+
+  describe :show_warning? do
+    subject { build.show_warning? }
+
+    %w(pending).each do |state|
+      context "if commit_status.status is #{state}" do
+        before { build.status = state }
+
+        it { is_expected.to be_truthy }
+
+        context "and there are specific runner" do
+          let(:runner) { FactoryGirl.create :ci_specific_runner, contacted_at: 1.second.ago }
+
+          before do
+            build.project.runners << runner
+            runner.save
+          end
+
+          it { is_expected.to be_falsey }
+        end
+      end
+    end
+
+    %w(success failed canceled running).each do |state|
+      context "if commit_status.status is #{state}" do
+        before { build.status = state }
+
+        it { is_expected.to be_falsey }
+      end
+    end
+  end
 end
diff --git a/spec/models/ci/commit_spec.rb b/spec/models/ci/commit_spec.rb
index acff1ddf0fcf274a1fef5112d3a2275d1dfb0f54..330971174fbb38c4afb11dcf080d8fd5f3478c77 100644
--- a/spec/models/ci/commit_spec.rb
+++ b/spec/models/ci/commit_spec.rb
@@ -23,6 +23,8 @@ describe Ci::Commit do
   let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project }
 
   it { is_expected.to belong_to(:gl_project) }
+  it { is_expected.to have_many(:statuses) }
+  it { is_expected.to have_many(:trigger_requests) }
   it { is_expected.to have_many(:builds) }
   it { is_expected.to validate_presence_of :sha }
 
@@ -47,10 +49,12 @@ describe Ci::Commit do
       @second = FactoryGirl.create :ci_build, commit: commit
     end
 
-    it "creates new build" do
+    it "creates only a new build" do
       expect(commit.builds.count(:all)).to eq 2
+      expect(commit.statuses.count(:all)).to eq 2
       commit.retry
       expect(commit.builds.count(:all)).to eq 3
+      expect(commit.statuses.count(:all)).to eq 3
     end
   end
 
@@ -78,8 +82,8 @@ describe Ci::Commit do
     subject { commit.stage }
 
     before do
-      @second = FactoryGirl.create :ci_build, commit: commit, name: 'deploy', stage: 'deploy', stage_idx: 1, status: :pending
-      @first = FactoryGirl.create :ci_build, commit: commit, name: 'test', stage: 'test', stage_idx: 0, status: :pending
+      @second = FactoryGirl.create :commit_status, commit: commit, name: 'deploy', stage: 'deploy', stage_idx: 1, status: 'pending'
+      @first = FactoryGirl.create :commit_status, commit: commit, name: 'test', stage: 'test', stage_idx: 0, status: 'pending'
     end
 
     it 'returns first running stage' do
@@ -88,7 +92,7 @@ describe Ci::Commit do
 
     context 'first build succeeded' do
       before do
-        @first.update_attributes(status: :success)
+        @first.success
       end
 
       it 'returns last running stage' do
@@ -98,8 +102,8 @@ describe Ci::Commit do
 
     context 'all builds succeeded' do
       before do
-        @first.update_attributes(status: :success)
-        @second.update_attributes(status: :success)
+        @first.success
+        @second.success
       end
 
       it 'returns nil' do
@@ -111,6 +115,33 @@ describe Ci::Commit do
   describe :create_next_builds do
   end
 
+  describe :refs do
+    subject { commit.refs }
+
+    before do
+      FactoryGirl.create :commit_status, commit: commit, name: 'deploy'
+      FactoryGirl.create :commit_status, commit: commit, name: 'deploy', ref: 'develop'
+      FactoryGirl.create :commit_status, commit: commit, name: 'deploy', ref: 'master'
+    end
+
+    it 'returns all refs' do
+      is_expected.to contain_exactly('master', 'develop', nil)
+    end
+  end
+
+  describe :retried do
+    subject { commit.retried }
+
+    before do
+      @commit1 = FactoryGirl.create :ci_build, commit: commit, name: 'deploy'
+      @commit2 = FactoryGirl.create :ci_build, commit: commit, name: 'deploy'
+    end
+
+    it 'returns old builds' do
+      is_expected.to contain_exactly(@commit1)
+    end
+  end
+
   describe :create_builds do
     let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project }
 
@@ -194,9 +225,10 @@ describe Ci::Commit do
         it 'rebuilds commit' do
           expect(commit.status).to eq('skipped')
           expect(create_builds(trigger_request)).to be_truthy
-          commit.builds.reload
-          expect(commit.builds.size).to eq(2)
-          expect(commit.status).to eq('pending')
+
+          # since everything in Ci::Commit is cached we need to fetch a new object
+          new_commit = Ci::Commit.find_by_id(commit.id)
+          expect(new_commit.status).to eq('pending')
         end
       end
     end
@@ -252,10 +284,10 @@ describe Ci::Commit do
 
   describe :should_create_next_builds? do
     before do
-      @build1 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'master', tag: false, status: :success
-      @build2 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'develop', tag: false, status: :failed
-      @build3 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'master', tag: true, status: :failed
-      @build4 = FactoryGirl.create :ci_build, commit: commit, name: 'build4', ref: 'master', tag: false, status: :success
+      @build1 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'master', tag: false, status: 'success'
+      @build2 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'develop', tag: false, status: 'failed'
+      @build3 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'master', tag: true, status: 'failed'
+      @build4 = FactoryGirl.create :ci_build, commit: commit, name: 'build4', ref: 'master', tag: false, status: 'success'
     end
 
     context 'for success' do
@@ -266,7 +298,7 @@ describe Ci::Commit do
 
     context 'for failed' do
       before do
-        @build4.update_attributes(status: :failed)
+        @build4.update_attributes(status: 'failed')
       end
 
       it 'to not create' do
@@ -286,7 +318,7 @@ describe Ci::Commit do
 
     context 'for running' do
       before do
-        @build4.update_attributes(status: :running)
+        @build4.update_attributes(status: 'running')
       end
 
       it 'to not create' do
@@ -296,7 +328,7 @@ describe Ci::Commit do
 
     context 'for retried' do
       before do
-        @build5 = FactoryGirl.create :ci_build, commit: commit, name: 'build4', ref: 'master', tag: false, status: :failed
+        @build5 = FactoryGirl.create :ci_build, commit: commit, name: 'build4', ref: 'master', tag: false, status: 'failed'
       end
 
       it 'to not create' do
diff --git a/spec/models/ci/project_services/mail_service_spec.rb b/spec/models/ci/project_services/mail_service_spec.rb
index 04e870dce7f5d36778f61afb7736fc9825153789..d9b3d34ff1529bd04343f399b4b2fef6aac60a35 100644
--- a/spec/models/ci/project_services/mail_service_spec.rb
+++ b/spec/models/ci/project_services/mail_service_spec.rb
@@ -35,7 +35,7 @@ describe Ci::MailService do
       let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true) }
       let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
       let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
-      let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit, user: user) }
+      let(:build) { FactoryGirl.create(:ci_build, status: 'failed', commit: commit, user: user) }
 
       before do
         allow(mail).to receive_messages(
@@ -58,7 +58,7 @@ describe Ci::MailService do
       let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true, email_only_broken_builds: false) }
       let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
       let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
-      let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) }
+      let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) }
 
       before do
         allow(mail).to receive_messages(
@@ -86,7 +86,7 @@ describe Ci::MailService do
       end
       let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
       let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
-      let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) }
+      let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) }
 
       before do
         allow(mail).to receive_messages(
@@ -115,7 +115,7 @@ describe Ci::MailService do
       end
       let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
       let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
-      let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) }
+      let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) }
 
       before do
         allow(mail).to receive_messages(
@@ -144,7 +144,7 @@ describe Ci::MailService do
       end
       let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
       let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
-      let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) }
+      let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) }
 
       before do
         allow(mail).to receive_messages(
@@ -167,7 +167,7 @@ describe Ci::MailService do
       end
       let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
       let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
-      let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit, user: user) }
+      let(:build) { FactoryGirl.create(:ci_build, status: 'failed', commit: commit, user: user) }
 
       before do
         allow(mail).to receive_messages(
diff --git a/spec/models/ci/project_spec.rb b/spec/models/ci/project_spec.rb
index dec4720a711b74c3e6ad1f00da8694cd651997f4..c1605d688597a081041213eac5c237e7f423c038 100644
--- a/spec/models/ci/project_spec.rb
+++ b/spec/models/ci/project_spec.rb
@@ -259,5 +259,18 @@ describe Ci::Project do
       FactoryGirl.create(:ci_shared_runner)
       expect(project.any_runners?).to be_falsey
     end
+
+    it "checks the presence of specific runner" do
+      project = FactoryGirl.create(:ci_project)
+      specific_runner = FactoryGirl.create(:ci_specific_runner)
+      project.runners << specific_runner
+      expect(project.any_runners? { |runner| runner == specific_runner }).to be_truthy
+    end
+
+    it "checks the presence of shared runner" do
+      project = FactoryGirl.create(:ci_project, shared_runners_enabled: true)
+      shared_runner = FactoryGirl.create(:ci_shared_runner)
+      expect(project.any_runners? { |runner| runner == shared_runner }).to be_truthy
+    end
   end
 end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 757593a7ab8f090b80f9ad63cd8a926f84c5ae03..536a737a33d44af88af26506ff1f369cb599bd77 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -48,6 +48,71 @@ describe Ci::Runner do
     it { expect(shared_runner.only_for?(project)).to be_truthy }
   end
 
+  describe :online do
+    subject { Ci::Runner.online }
+
+    before do
+      @runner1 = FactoryGirl.create(:ci_shared_runner, contacted_at: 1.year.ago)
+      @runner2 = FactoryGirl.create(:ci_shared_runner, contacted_at: 1.second.ago)
+    end
+
+    it { is_expected.to eq([@runner2])}
+  end
+
+  describe :online? do
+    let(:runner) { FactoryGirl.create(:ci_shared_runner) }
+
+    subject { runner.online? }
+
+    context 'never contacted' do
+      before { runner.contacted_at = nil }
+
+      it { is_expected.to be_falsey }
+    end
+
+    context 'contacted long time ago time' do
+      before { runner.contacted_at = 1.year.ago }
+
+      it { is_expected.to be_falsey }
+    end
+
+    context 'contacted 1s ago' do
+      before { runner.contacted_at = 1.second.ago }
+
+      it { is_expected.to be_truthy }
+    end
+  end
+
+  describe :status do
+    let(:runner) { FactoryGirl.create(:ci_shared_runner, contacted_at: 1.second.ago) }
+
+    subject { runner.status }
+
+    context 'never connected' do
+      before { runner.contacted_at = nil }
+
+      it { is_expected.to eq(:not_connected) }
+    end
+
+    context 'contacted 1s ago' do
+      before { runner.contacted_at = 1.second.ago }
+
+      it { is_expected.to eq(:online) }
+    end
+
+    context 'contacted long time ago' do
+      before { runner.contacted_at = 1.year.ago }
+
+      it { is_expected.to eq(:offline) }
+    end
+
+    context 'inactive' do
+      before { runner.active = false }
+
+      it { is_expected.to eq(:paused) }
+    end
+  end
+
   describe "belongs_to_one_project?" do
     it "returns false if there are two projects runner assigned to" do
       runner = FactoryGirl.create(:ci_specific_runner)
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index e303a97e6b55edd290ced7c3b79f93f5d6934cfd..90be93249511f5b8eef45d4b5d65587758c37553 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -89,9 +89,9 @@ eos
   end
 
   it_behaves_like 'a mentionable' do
-    subject { commit }
+    subject { create(:project).commit }
 
-    let(:author) { create(:user, email: commit.author_email) }
+    let(:author) { create(:user, email: subject.author_email) }
     let(:backref_text) { "commit #{subject.id}" }
     let(:set_mentionable_text) do
       ->(txt) { allow(subject).to receive(:safe_message).and_return(txt) }
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c96a606fdaab60445d7415e85763049530672317
--- /dev/null
+++ b/spec/models/commit_status_spec.rb
@@ -0,0 +1,164 @@
+require 'spec_helper'
+
+describe CommitStatus do
+  let(:commit) { FactoryGirl.create :ci_commit }
+  let(:commit_status) { FactoryGirl.create :commit_status, commit: commit }
+
+  it { is_expected.to belong_to(:commit) }
+  it { is_expected.to belong_to(:user) }
+  it { is_expected.to validate_presence_of(:name) }
+  it { is_expected.to validate_inclusion_of(:status).in_array(%w(pending running failed success canceled)) }
+
+  it { is_expected.to delegate_method(:sha).to(:commit) }
+  it { is_expected.to delegate_method(:short_sha).to(:commit) }
+  it { is_expected.to delegate_method(:gl_project).to(:commit) }
+  
+  it { is_expected.to respond_to :success? }
+  it { is_expected.to respond_to :failed? }
+  it { is_expected.to respond_to :running? }
+  it { is_expected.to respond_to :pending? }
+
+  describe :author do
+    subject { commit_status.author }
+    before { commit_status.author = User.new }
+
+    it { is_expected.to eq(commit_status.user) }
+  end
+
+  describe :started? do
+    subject { commit_status.started? }
+
+    context 'without started_at' do
+      before { commit_status.started_at = nil }
+
+      it { is_expected.to be_falsey }
+    end
+
+    %w(running success failed).each do |status|
+      context "if commit status is #{status}" do
+        before { commit_status.status = status }
+
+        it { is_expected.to be_truthy }
+      end
+    end
+
+    %w(pending canceled).each do |status|
+      context "if commit status is #{status}" do
+        before { commit_status.status = status }
+
+        it { is_expected.to be_falsey }
+      end
+    end
+  end
+
+  describe :active? do
+    subject { commit_status.active? }
+
+    %w(pending running).each do |state|
+      context "if commit_status.status is #{state}" do
+        before { commit_status.status = state }
+
+        it { is_expected.to be_truthy }
+      end
+    end
+
+    %w(success failed canceled).each do |state|
+      context "if commit_status.status is #{state}" do
+        before { commit_status.status = state }
+
+        it { is_expected.to be_falsey }
+      end
+    end
+  end
+
+  describe :complete? do
+    subject { commit_status.complete? }
+
+    %w(success failed canceled).each do |state|
+      context "if commit_status.status is #{state}" do
+        before { commit_status.status = state }
+
+        it { is_expected.to be_truthy }
+      end
+    end
+
+    %w(pending running).each do |state|
+      context "if commit_status.status is #{state}" do
+        before { commit_status.status = state }
+
+        it { is_expected.to be_falsey }
+      end
+    end
+  end
+
+  describe :duration do
+    subject { commit_status.duration }
+
+    it { is_expected.to eq(120.0) }
+
+    context 'if the building process has not started yet' do
+      before do
+        commit_status.started_at = nil
+        commit_status.finished_at = nil
+      end
+
+      it { is_expected.to be_nil }
+    end
+
+    context 'if the building process has started' do
+      before do
+        commit_status.started_at = Time.now - 1.minute
+        commit_status.finished_at = nil
+      end
+
+      it { is_expected.to be_a(Float) }
+      it { is_expected.to be > 0.0 }
+    end
+  end
+  
+  describe :latest do
+    subject { CommitStatus.latest.order(:id) }
+
+    before do
+      @commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running'
+      @commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending'
+      @commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'cc', status: 'success'
+      @commit4 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'bb', status: 'success'
+      @commit5 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'success'
+    end
+
+    it 'return unique statuses' do
+      is_expected.to eq([@commit2, @commit3, @commit4, @commit5])
+    end
+  end
+
+  describe :for_ref do
+    subject { CommitStatus.for_ref('bb').order(:id) }
+
+    before do
+      @commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running'
+      @commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending'
+      @commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: nil, status: 'success'
+    end
+
+    it 'return statuses with equal and nil ref set' do
+      is_expected.to eq([@commit1])
+    end
+  end
+
+  describe :running_or_pending do
+    subject { CommitStatus.running_or_pending.order(:id) }
+
+    before do
+      @commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running'
+      @commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending'
+      @commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: nil, status: 'success'
+      @commit4 = FactoryGirl.create :commit_status, commit: commit, name: 'dd', ref: nil, status: 'failed'
+      @commit5 = FactoryGirl.create :commit_status, commit: commit, name: 'ee', ref: nil, status: 'canceled'
+    end
+
+    it 'return statuses that are running or pending' do
+      is_expected.to eq([@commit1, @commit2])
+    end
+  end
+end
diff --git a/spec/models/concerns/case_sensitivity_spec.rb b/spec/models/concerns/case_sensitivity_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f7ed30f81984a27a5e2b6a1f21bebee1f9e8feb0
--- /dev/null
+++ b/spec/models/concerns/case_sensitivity_spec.rb
@@ -0,0 +1,189 @@
+require 'spec_helper'
+
+describe CaseSensitivity do
+  describe '.iwhere' do
+    let(:connection) { ActiveRecord::Base.connection }
+    let(:model)      { Class.new { include CaseSensitivity } }
+
+    describe 'using PostgreSQL' do
+      before do
+        allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
+        allow(Gitlab::Database).to receive(:mysql?).and_return(false)
+      end
+
+      describe 'with a single column/value pair' do
+        it 'returns the criteria for a column and a value' do
+          criteria = double(:criteria)
+
+          expect(connection).to receive(:quote_table_name).
+            with(:foo).
+            and_return('"foo"')
+
+          expect(model).to receive(:where).
+            with(%q{LOWER("foo") = LOWER(:value)}, value: 'bar').
+            and_return(criteria)
+
+          expect(model.iwhere(foo: 'bar')).to eq(criteria)
+        end
+
+        it 'returns the criteria for a column with a table, and a value' do
+          criteria = double(:criteria)
+
+          expect(connection).to receive(:quote_table_name).
+            with(:'foo.bar').
+            and_return('"foo"."bar"')
+
+          expect(model).to receive(:where).
+            with(%q{LOWER("foo"."bar") = LOWER(:value)}, value: 'bar').
+            and_return(criteria)
+
+          expect(model.iwhere(:'foo.bar' => 'bar')).to eq(criteria)
+        end
+      end
+
+      describe 'with multiple column/value pairs' do
+        it 'returns the criteria for a column and a value' do
+          initial = double(:criteria)
+          final   = double(:criteria)
+
+          expect(connection).to receive(:quote_table_name).
+            with(:foo).
+            and_return('"foo"')
+
+          expect(connection).to receive(:quote_table_name).
+            with(:bar).
+            and_return('"bar"')
+
+          expect(model).to receive(:where).
+            with(%q{LOWER("foo") = LOWER(:value)}, value: 'bar').
+            and_return(initial)
+
+          expect(initial).to receive(:where).
+            with(%q{LOWER("bar") = LOWER(:value)}, value: 'baz').
+            and_return(final)
+
+          got = model.iwhere(foo: 'bar', bar: 'baz')
+
+          expect(got).to eq(final)
+        end
+
+        it 'returns the criteria for a column with a table, and a value' do
+          initial = double(:criteria)
+          final   = double(:criteria)
+
+          expect(connection).to receive(:quote_table_name).
+            with(:'foo.bar').
+            and_return('"foo"."bar"')
+
+          expect(connection).to receive(:quote_table_name).
+            with(:'foo.baz').
+            and_return('"foo"."baz"')
+
+          expect(model).to receive(:where).
+            with(%q{LOWER("foo"."bar") = LOWER(:value)}, value: 'bar').
+            and_return(initial)
+
+          expect(initial).to receive(:where).
+            with(%q{LOWER("foo"."baz") = LOWER(:value)}, value: 'baz').
+            and_return(final)
+
+          got = model.iwhere(:'foo.bar' => 'bar',
+                             :'foo.baz' => 'baz')
+
+          expect(got).to eq(final)
+        end
+      end
+    end
+
+    describe 'using MySQL' do
+      before do
+        allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
+        allow(Gitlab::Database).to receive(:mysql?).and_return(true)
+      end
+
+      describe 'with a single column/value pair' do
+        it 'returns the criteria for a column and a value' do
+          criteria = double(:criteria)
+
+          expect(connection).to receive(:quote_table_name).
+            with(:foo).
+            and_return('`foo`')
+
+          expect(model).to receive(:where).
+            with(%q{`foo` = :value}, value: 'bar').
+            and_return(criteria)
+
+          expect(model.iwhere(foo: 'bar')).to eq(criteria)
+        end
+
+        it 'returns the criteria for a column with a table, and a value' do
+          criteria = double(:criteria)
+
+          expect(connection).to receive(:quote_table_name).
+            with(:'foo.bar').
+            and_return('`foo`.`bar`')
+
+          expect(model).to receive(:where).
+            with(%q{`foo`.`bar` = :value}, value: 'bar').
+            and_return(criteria)
+
+          expect(model.iwhere(:'foo.bar' => 'bar')).
+            to eq(criteria)
+        end
+      end
+
+      describe 'with multiple column/value pairs' do
+        it 'returns the criteria for a column and a value' do
+          initial = double(:criteria)
+          final   = double(:criteria)
+
+          expect(connection).to receive(:quote_table_name).
+            with(:foo).
+            and_return('`foo`')
+
+          expect(connection).to receive(:quote_table_name).
+            with(:bar).
+            and_return('`bar`')
+
+          expect(model).to receive(:where).
+            with(%q{`foo` = :value}, value: 'bar').
+            and_return(initial)
+
+          expect(initial).to receive(:where).
+            with(%q{`bar` = :value}, value: 'baz').
+            and_return(final)
+
+          got = model.iwhere(foo: 'bar', bar: 'baz')
+
+          expect(got).to eq(final)
+        end
+
+        it 'returns the criteria for a column with a table, and a value' do
+          initial = double(:criteria)
+          final   = double(:criteria)
+
+          expect(connection).to receive(:quote_table_name).
+            with(:'foo.bar').
+            and_return('`foo`.`bar`')
+
+          expect(connection).to receive(:quote_table_name).
+            with(:'foo.baz').
+            and_return('`foo`.`baz`')
+
+          expect(model).to receive(:where).
+            with(%q{`foo`.`bar` = :value}, value: 'bar').
+            and_return(initial)
+
+          expect(initial).to receive(:where).
+            with(%q{`foo`.`baz` = :value}, value: 'baz').
+            and_return(final)
+
+          got = model.iwhere(:'foo.bar' => 'bar',
+                             :'foo.baz' => 'baz')
+
+          expect(got).to eq(final)
+        end
+      end
+    end
+  end
+end
diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb
index 2d6fe003215599acaf050a959299ab5d42ceadf6..6179882e93591f4556ddc9062b5c3ebba2dd14c0 100644
--- a/spec/models/concerns/mentionable_spec.rb
+++ b/spec/models/concerns/mentionable_spec.rb
@@ -25,7 +25,7 @@ describe Issue, "Mentionable" do
     it 'correctly removes already-mentioned Commits' do
       expect(SystemNoteService).not_to receive(:cross_reference)
 
-      issue.create_cross_references!(project, author, [commit2])
+      issue.create_cross_references!(author, [commit2])
     end
   end
 
diff --git a/spec/models/generic_commit_status_spec.rb b/spec/models/generic_commit_status_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f442fa5fbe5f608b80f68dcddca4d215575e23b3
--- /dev/null
+++ b/spec/models/generic_commit_status_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe GenericCommitStatus do
+  let(:commit) { FactoryGirl.create :ci_commit }
+  let(:generic_commit_status) { FactoryGirl.create :generic_commit_status, commit: commit }
+
+  describe :context do
+    subject { generic_commit_status.context }
+    before { generic_commit_status.context = 'my_context' }
+
+    it { is_expected.to eq(generic_commit_status.name) }
+  end
+
+  describe :tags do
+    subject { generic_commit_status.tags }
+
+    it { is_expected.to eq([:external]) }
+  end
+
+  describe :set_default_values do
+    before do
+      generic_commit_status.context = nil
+      generic_commit_status.stage = nil
+      generic_commit_status.save
+    end
+
+    describe :context do
+      subject { generic_commit_status.context }
+
+      it { is_expected.to_not be_nil }
+    end
+
+    describe :stage do
+      subject { generic_commit_status.stage }
+
+      it { is_expected.to_not be_nil }
+    end
+  end
+end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index cf336d829579ee7c4477bf06b27a9497ae65479d..623332cd2f95c16784f6958ad5443194cf4c78bf 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -69,7 +69,7 @@ describe Issue do
   end
 
   it_behaves_like 'an editable mentionable' do
-    subject { create(:issue, project: project) }
+    subject { create(:issue) }
 
     let(:backref_text) { "issue #{subject.to_reference}" }
     let(:set_mentionable_text) { ->(txt){ subject.description = txt } }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 17a49013d2515bb4f1e7349808c0990b4a57219b..6aaf1c036b05aa231ed9a7fdd9a64865b1f80d9a 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -165,6 +165,17 @@ describe MergeRequest do
     end
   end
 
+  describe "#hook_attrs" do
+    it "has all the required keys" do
+      attrs = subject.hook_attrs
+      attrs = attrs.to_h
+      expect(attrs).to include(:source)
+      expect(attrs).to include(:target)
+      expect(attrs).to include(:last_commit)
+      expect(attrs).to include(:work_in_progress)
+    end
+  end
+
   it_behaves_like 'an editable mentionable' do
     subject { create(:merge_request) }
 
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 3a0b194ba1e236d49d4a87c54400d280a710c084..75564839dcfb6baac5c2b44357b1184cd5fc0b73 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -192,10 +192,9 @@ describe Note do
   end
 
   it_behaves_like 'an editable mentionable' do
-    subject { create :note, noteable: issue, project: project }
+    subject { create :note, noteable: issue, project: issue.project }
 
-    let(:project) { create(:project) }
-    let(:issue) { create :issue, project: project }
+    let(:issue) { create :issue }
     let(:backref_text) { issue.gfm_reference }
     let(:set_mentionable_text) { ->(txt) { subject.note = txt } }
   end
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f8a3493f52df63b0c050b7da3f6d2a936273c9a5
--- /dev/null
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -0,0 +1,56 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+
+require 'spec_helper'
+
+describe BambooService, models: true do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Execute" do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project) }
+
+    before do
+      @bamboo_service = BambooService.create(
+        project: create(:project),
+        properties: {
+          bamboo_url: 'http://gitlab.com',
+          username: 'mic',
+          password: "password"
+        }
+      )
+    end
+
+    it "reset password if url changed" do
+      @bamboo_service.bamboo_url = 'http://gitlab1.com'
+      @bamboo_service.save
+      expect(@bamboo_service.password).to be_nil
+    end
+
+    it "does not reset password if username changed" do
+      @bamboo_service.username = "some_name"
+      @bamboo_service.save
+      expect(@bamboo_service.password).to eq("password")
+    end
+  end
+end
diff --git a/spec/models/project_services/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb
index c0b8a144c3add3279e20367f181a29cab2847599..842089ebe0d66b9eae8fffda30c069838931b054 100644
--- a/spec/models/project_services/gitlab_ci_service_spec.rb
+++ b/spec/models/project_services/gitlab_ci_service_spec.rb
@@ -39,8 +39,7 @@ describe GitlabCiService do
     end
 
     describe :build_page do
-      it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://localhost/ci/projects/#{@ci_project.id}/commits/2ab7834c")}
-      it { expect(@service.build_page("issue#2", 'master')).to eq("http://localhost/ci/projects/#{@ci_project.id}/commits/issue%232")}
+      it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://localhost/#{@ci_project.gl_project.path_with_namespace}/commit/2ab7834c/ci")}
     end
 
     describe "execute" do
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3dbd2346bccd0eff9966e16382efa19f8f72f1ab
--- /dev/null
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -0,0 +1,56 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+
+require 'spec_helper'
+
+describe TeamcityService, models: true do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Execute" do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project) }
+
+    before do
+      @teamcity_service = TeamcityService.create(
+        project: create(:project),
+        properties: {
+          teamcity_url: 'http://gitlab.com',
+          username: 'mic',
+          password: "password"
+        }
+      )
+    end
+
+    it "reset password if url changed" do
+      @teamcity_service.teamcity_url = 'http://gitlab1.com'
+      @teamcity_service.save
+      expect(@teamcity_service.password).to be_nil
+    end
+
+    it "does not reset password if username changed" do
+      @teamcity_service.username = "some_name"
+      @teamcity_service.save
+      expect(@teamcity_service.password).to eq("password")
+    end
+  end
+end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 8b5d2c3a1c105c6533ce6b2b6e62c51c283bfd20..f93935ebe3b057e8e69be5c6b8bf12f4382f34a3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -423,4 +423,42 @@ describe Project do
     it { expect(project.gitlab_ci?).to be_truthy }
     it { expect(project.gitlab_ci_project).to be_a(Ci::Project) }
   end
+
+  describe '.trending' do
+    let(:group)    { create(:group) }
+    let(:project1) { create(:empty_project, :public, group: group) }
+    let(:project2) { create(:empty_project, :public, group: group) }
+
+    before do
+      2.times do
+        create(:note_on_commit, project: project1)
+      end
+
+      create(:note_on_commit, project: project2)
+    end
+
+    describe 'without an explicit start date' do
+      subject { described_class.trending.to_a }
+
+      it 'sorts Projects by the amount of notes in descending order' do
+        expect(subject).to eq([project1, project2])
+      end
+    end
+
+    describe 'with an explicit start date' do
+      let(:date) { 2.months.ago }
+
+      subject { described_class.trending(date).to_a }
+
+      before do
+        2.times do
+          create(:note_on_commit, project: project2, created_at: date)
+        end
+      end
+
+      it 'sorts Projects by the amount of notes in descending order' do
+        expect(subject).to eq([project2, project1])
+      end
+    end
+  end
 end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index a213ffe6c4b33bbdda75fb6f9d6a44fe33f3de4a..da87ea5b84f175ce7835d6708021cf03558bf10d 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -103,4 +103,27 @@ describe Service do
       end
     end
   end
+
+  describe "#prop_updated?" do
+    let(:service) do
+      BambooService.create(
+        project: create(:project),
+        properties: {
+          bamboo_url: 'http://gitlab.com',
+          username: 'mic',
+          password: "password"
+        }
+      )
+    end
+
+    it "returns false" do
+      service.username = "key_changed"
+      expect(service.prop_updated?(:bamboo_url)).to be_falsy
+    end
+
+    it "returns true" do
+      service.bamboo_url = "http://other.com"
+      expect(service.prop_updated?(:bamboo_url)).to be_truthy
+    end
+  end
 end
diff --git a/spec/requests/api/commit_status_spec.rb b/spec/requests/api/commit_status_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b9e6dfc15a796c5ac5b6db2bd0c343ef11e5d594
--- /dev/null
+++ b/spec/requests/api/commit_status_spec.rb
@@ -0,0 +1,135 @@
+require 'spec_helper'
+
+describe API::API, api: true do
+  include ApiHelpers
+  let(:user) { create(:user) }
+  let(:user2) { create(:user) }
+  let!(:project) { create(:project, creator_id: user.id) }
+  let!(:reporter) { create(:project_member, user: user, project: project, access_level: ProjectMember::REPORTER) }
+  let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) }
+  let(:commit) { project.repository.commit }
+  let!(:ci_commit) { project.ensure_ci_commit(commit.id) }
+  let(:commit_status) { create(:commit_status, commit: ci_commit) }
+
+  describe "GET /projects/:id/repository/commits/:sha/statuses" do
+    context "reporter user" do
+      let(:statuses_id) { json_response.map { |status| status['id'] } }
+
+      before do
+        @status1 = create(:commit_status, commit: ci_commit, status: 'running')
+        @status2 = create(:commit_status, commit: ci_commit, name: 'coverage', status: 'pending')
+        @status3 = create(:commit_status, commit: ci_commit, name: 'coverage', ref: 'develop', status: 'running')
+        @status4 = create(:commit_status, commit: ci_commit, name: 'coverage', status: 'success')
+        @status5 = create(:commit_status, commit: ci_commit, ref: 'develop', status: 'success')
+        @status6 = create(:commit_status, commit: ci_commit, status: 'success')
+      end
+
+      it "should return latest commit statuses" do
+        get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user)
+        expect(response.status).to eq(200)
+
+        expect(json_response).to be_an Array
+        expect(statuses_id).to contain_exactly(@status3.id, @status4.id, @status5.id, @status6.id)
+      end
+
+      it "should return all commit statuses" do
+        get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?all=1", user)
+        expect(response.status).to eq(200)
+
+        expect(json_response).to be_an Array
+        expect(statuses_id).to contain_exactly(@status1.id, @status2.id, @status3.id, @status4.id, @status5.id, @status6.id)
+      end
+
+      it "should return latest commit statuses for specific ref" do
+        get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?ref=develop", user)
+        expect(response.status).to eq(200)
+
+        expect(json_response).to be_an Array
+        expect(statuses_id).to contain_exactly(@status3.id, @status5.id)
+      end
+
+      it "should return latest commit statuses for specific name" do
+        get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?name=coverage", user)
+        expect(response.status).to eq(200)
+
+        expect(json_response).to be_an Array
+        expect(statuses_id).to contain_exactly(@status3.id, @status4.id)
+      end
+    end
+
+    context "guest user" do
+      it "should not return project commits" do
+        get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user2)
+        expect(response.status).to eq(403)
+      end
+    end
+
+    context "unauthorized user" do
+      it "should not return project commits" do
+        get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses")
+        expect(response.status).to eq(401)
+      end
+    end
+  end
+
+  describe 'POST /projects/:id/statuses/:sha' do
+    let(:post_url) { "/projects/#{project.id}/statuses/#{commit.id}" }
+
+    context 'reporter user' do
+      context 'should create commit status' do
+        it 'with only required parameters' do
+          post api(post_url, user), state: 'success'
+          expect(response.status).to eq(201)
+          expect(json_response['sha']).to eq(commit.id)
+          expect(json_response['status']).to eq('success')
+          expect(json_response['name']).to eq('default')
+          expect(json_response['ref']).to be_nil
+          expect(json_response['target_url']).to be_nil
+          expect(json_response['description']).to be_nil
+        end
+
+        it 'with all optional parameters' do
+          post api(post_url, user), state: 'success', context: 'coverage', ref: 'develop', target_url: 'url', description: 'test'
+          expect(response.status).to eq(201)
+          expect(json_response['sha']).to eq(commit.id)
+          expect(json_response['status']).to eq('success')
+          expect(json_response['name']).to eq('coverage')
+          expect(json_response['ref']).to eq('develop')
+          expect(json_response['target_url']).to eq('url')
+          expect(json_response['description']).to eq('test')
+        end
+      end
+
+      context 'should not create commit status' do
+        it 'with invalid state' do
+          post api(post_url, user), state: 'invalid'
+          expect(response.status).to eq(400)
+        end
+
+        it 'without state' do
+          post api(post_url, user)
+          expect(response.status).to eq(400)
+        end
+
+        it 'invalid commit' do
+          post api("/projects/#{project.id}/statuses/invalid_sha", user), state: 'running'
+          expect(response.status).to eq(404)
+        end
+      end
+    end
+
+    context 'guest user' do
+      it 'should not create commit status' do
+        post api(post_url, user2)
+        expect(response.status).to eq(403)
+      end
+    end
+
+    context 'unauthorized user' do
+      it 'should not create commit status' do
+        post api(post_url)
+        expect(response.status).to eq(401)
+      end
+    end
+  end
+end
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index a1c248c636eb4fa699777f8accd71e6fb84a30f2..49acc3368f43a536b972df9e8015e117d82db02e 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -47,6 +47,19 @@ describe API::API, api: true  do
         get api("/projects/#{project.id}/repository/commits/invalid_sha", user)
         expect(response.status).to eq(404)
       end
+
+      it "should return not_found for CI status" do
+        get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
+        expect(response.status).to eq(200)
+        expect(json_response['status']).to eq('not_found')
+      end
+
+      it "should return status for CI" do
+        ci_commit = project.ensure_ci_commit(project.repository.commit.sha)
+        get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
+        expect(response.status).to eq(200)
+        expect(json_response['status']).to eq(ci_commit.status)
+      end
     end
 
     context "unauthorized user" do
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index 9aa60826f21448cd4360eafde6b5049a2562eec8..c0226605a2320aebc5f85bea2daaeb5e6ba8ba86 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -3,6 +3,8 @@ require "spec_helper"
 describe API::API, api: true  do
   include ApiHelpers
   let(:user) { create(:user) }
+  let(:admin) { create(:admin) }
+  let(:user2) { create(:user) }
   let(:project) {create(:project, creator_id: user.id, namespace: user.namespace) }
 
   Service.available_services_names.each do |service|
@@ -51,11 +53,40 @@ describe API::API, api: true  do
     describe "GET /projects/:id/services/#{service.dasherize}" do
       include_context service
 
-      it "should get #{service} settings" do
+      # inject some properties into the service
+      before do
+        project.build_missing_services
+        service_object = project.send(service_method)
+        service_object.properties = service_attrs
+        service_object.save
+      end
+
+      it 'should return authentication error when unauthenticated' do
+        get api("/projects/#{project.id}/services/#{dashed_service}")
+        expect(response.status).to eq(401)
+      end
+      
+      it "should return all properties of service #{service} when authenticated as admin" do
+        get api("/projects/#{project.id}/services/#{dashed_service}", admin)
+        
+        expect(response.status).to eq(200)
+        expect(json_response['properties'].keys.map(&:to_sym)).to match_array(service_attrs_list.map)
+      end
+
+      it "should return properties of service #{service} other than passwords when authenticated as project owner" do
         get api("/projects/#{project.id}/services/#{dashed_service}", user)
 
         expect(response.status).to eq(200)
+        expect(json_response['properties'].keys.map(&:to_sym)).to match_array(service_attrs_list_without_passwords)
       end
+
+      it "should return error when authenticated but not a project owner" do
+        project.team << [user2, :developer]
+        get api("/projects/#{project.id}/services/#{dashed_service}", user2)
+        
+        expect(response.status).to eq(403)
+      end
+
     end
   end
 end
diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb
index 54c1d0199f6a88b57026a882ee6b42df3259f166..88218a93e1f589b90e015b20bde21c28fe9d59c4 100644
--- a/spec/requests/ci/api/builds_spec.rb
+++ b/spec/requests/ci/api/builds_spec.rb
@@ -76,6 +76,8 @@ describe Ci::API::API do
 
         expect(response.status).to eq(201)
         expect(json_response["variables"]).to eq([
+          { "key" => "CI_BUILD_NAME", "value" => "spinach", "public" => true },
+          { "key" => "CI_BUILD_STAGE", "value" => "test", "public" => true },
           { "key" => "DB_NAME", "value" => "postgres", "public" => true },
           { "key" => "SECRET_KEY", "value" => "secret_value", "public" => false },
         ])
@@ -93,6 +95,9 @@ describe Ci::API::API do
 
         expect(response.status).to eq(201)
         expect(json_response["variables"]).to eq([
+          { "key" => "CI_BUILD_NAME", "value" => "spinach", "public" => true },
+          { "key" => "CI_BUILD_STAGE", "value" => "test", "public" => true },
+          { "key" => "CI_BUILD_TRIGGERED", "value" => "true", "public" => true },
           { "key" => "DB_NAME", "value" => "postgres", "public" => true },
           { "key" => "SECRET_KEY", "value" => "secret_value", "public" => false },
           { "key" => "TRIGGER_KEY", "value" => "TRIGGER_VALUE", "public" => false },
diff --git a/spec/requests/ci/builds_spec.rb b/spec/requests/ci/builds_spec.rb
deleted file mode 100644
index f68116c52aa9364c0f2014c0a807786874da7133..0000000000000000000000000000000000000000
--- a/spec/requests/ci/builds_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'spec_helper'
-
-describe "Builds" do
-  before do
-    @commit = FactoryGirl.create :ci_commit
-    @build = FactoryGirl.create :ci_build, commit: @commit
-  end
-
-  describe "GET /:project/builds/:id/status.json" do
-    before do
-      get status_ci_project_build_path(@commit.project, @build), format: :json
-    end
-
-    it { expect(response.status).to eq(200) }
-    it { expect(response.body).to include(@build.sha) }
-  end
-end
diff --git a/spec/requests/ci/commits_spec.rb b/spec/requests/ci/commits_spec.rb
deleted file mode 100644
index f43a3982d718ec2759e1700e79cebf74b9c22178..0000000000000000000000000000000000000000
--- a/spec/requests/ci/commits_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-describe "Commits" do
-  before do
-    @commit = FactoryGirl.create :ci_commit
-  end
-
-  describe "GET /:project/refs/:ref_name/commits/:id/status.json" do
-    before do
-      get status_ci_project_commits_path(@commit.project, @commit.sha), format: :json
-    end
-
-    it { expect(response.status).to eq(200) }
-    it { expect(response.body).to include(@commit.sha) }
-  end
-end
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index c483060fd73994235eb2c069bb936b79ce78ad60..fd72905c331ab3f72ed61d66b3f3834bb6cec0ae 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -155,7 +155,7 @@ describe GitPushService do
 
     before do
       allow(commit).to receive_messages(
-        safe_message: "this commit \n mentions ##{issue.id}",
+        safe_message: "this commit \n mentions #{issue.to_reference}",
         references: [issue],
         author_name: commit_author.name,
         author_email: commit_author.email
diff --git a/spec/services/projects/download_service_spec.rb b/spec/services/projects/download_service_spec.rb
index f12e09c58c36fb0f53bc9e8c0fb4c3e047bf8a82..ddee2e62dfcfed6e9289b4ef6be404566406f74a 100644
--- a/spec/services/projects/download_service_spec.rb
+++ b/spec/services/projects/download_service_spec.rb
@@ -37,7 +37,6 @@ describe Projects::DownloadService do
         it { expect(@link_to_file).to have_key('url') }
         it { expect(@link_to_file).to have_key('is_image') }
         it { expect(@link_to_file['is_image']).to be true }
-        it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") }
         it { expect(@link_to_file['url']).to match('rails_sample.jpg') }
         it { expect(@link_to_file['alt']).to eq('rails_sample') }
       end
@@ -52,7 +51,6 @@ describe Projects::DownloadService do
         it { expect(@link_to_file).to have_key('url') }
         it { expect(@link_to_file).to have_key('is_image') }
         it { expect(@link_to_file['is_image']).to be false }
-        it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") }
         it { expect(@link_to_file['url']).to match('doc_sample.txt') }
         it { expect(@link_to_file['alt']).to eq('doc_sample.txt') }
       end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index bb7da33b12e15f8eedc4bde0488268766bfacab1..47755bfc990311bdc420d1c0bf94d1fb75fab2d6 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -7,6 +7,8 @@ describe Projects::TransferService do
 
   context 'namespace -> namespace' do
     before do
+      allow_any_instance_of(Gitlab::UploadsTransfer).
+        to receive(:move_project).and_return(true)
       group.add_owner(user)
       @result = transfer_project(project, user, group)
     end
diff --git a/spec/services/projects/upload_service_spec.rb b/spec/services/projects/upload_service_spec.rb
index fa4ff6b01ad9993cfcc6fa2d1ed112e2dc08f347..1b1a80d1fe731931de7fabe31826750a5fb6b8d3 100644
--- a/spec/services/projects/upload_service_spec.rb
+++ b/spec/services/projects/upload_service_spec.rb
@@ -18,7 +18,6 @@ describe Projects::UploadService do
       it { expect(@link_to_file).to have_key(:is_image) }
       it { expect(@link_to_file).to have_value('banana_sample') }
       it { expect(@link_to_file[:is_image]).to equal(true) }
-      it { expect(@link_to_file[:url]).to match("/#{@project.path_with_namespace}") }
       it { expect(@link_to_file[:url]).to match('banana_sample.gif') }
     end
 
@@ -34,7 +33,6 @@ describe Projects::UploadService do
       it { expect(@link_to_file).to have_value('dk') }
       it { expect(@link_to_file).to have_key(:is_image) }
       it { expect(@link_to_file[:is_image]).to equal(true) }
-      it { expect(@link_to_file[:url]).to match("/#{@project.path_with_namespace}") }
       it { expect(@link_to_file[:url]).to match('dk.png') }
     end
 
@@ -49,7 +47,6 @@ describe Projects::UploadService do
       it { expect(@link_to_file).to have_key(:is_image) }
       it { expect(@link_to_file).to have_value('rails_sample') }
       it { expect(@link_to_file[:is_image]).to equal(true) }
-      it { expect(@link_to_file[:url]).to match("/#{@project.path_with_namespace}") }
       it { expect(@link_to_file[:url]).to match('rails_sample.jpg') }
     end
 
@@ -64,7 +61,6 @@ describe Projects::UploadService do
       it { expect(@link_to_file).to have_key(:is_image) }
       it { expect(@link_to_file).to have_value('doc_sample.txt') }
       it { expect(@link_to_file[:is_image]).to equal(false) }
-      it { expect(@link_to_file[:url]).to match("/#{@project.path_with_namespace}") }
       it { expect(@link_to_file[:url]).to match('doc_sample.txt') }
     end
 
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index 48c49e2f717bb4c7337ba5a38ae0711791bd96aa..a31fc1e4b0762ca49f8462e98646d0947f14e787 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -13,8 +13,8 @@ describe SystemHooksService do
     it { expect(event_data(user, :destroy)).to include(:event_name, :name, :created_at, :email, :user_id) }
     it { expect(event_data(project, :create)).to include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
     it { expect(event_data(project, :destroy)).to include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
-    it { expect(event_data(project_member, :create)).to include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
-    it { expect(event_data(project_member, :destroy)).to include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
+    it { expect(event_data(project_member, :create)).to include(:event_name, :created_at, :project_name, :project_path, :project_path_with_namespace, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
+    it { expect(event_data(project_member, :destroy)).to include(:event_name, :created_at, :project_name, :project_path, :project_path_with_namespace, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
     it { expect(event_data(key, :create)).to include(:username, :key, :id) }
     it { expect(event_data(key, :destroy)).to include(:username, :key, :id) }
 
diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb
index e3de0afb44825a6b84a7bb9723e22754dfb7538b..f584904845e63c1034274328dff93a6f0814d6af 100644
--- a/spec/support/mentionable_shared_examples.rb
+++ b/spec/support/mentionable_shared_examples.rb
@@ -5,7 +5,7 @@
 # - let(:set_mentionable_text) { lambda { |txt| "block that assigns txt to the subject's mentionable_text" } }
 
 def common_mentionable_setup
-  let(:project) { create :project }
+  let(:project) { subject.project }
   let(:author)  { subject.author }
 
   let(:mentioned_issue)  { create(:issue, project: project) }
@@ -65,7 +65,7 @@ shared_examples 'a mentionable' do
 
   it "extracts references from its reference property" do
     # De-duplicate and omit itself
-    refs = subject.references(project)
+    refs = subject.referenced_mentionables
     expect(refs.size).to eq(6)
     expect(refs).to include(mentioned_issue)
     expect(refs).to include(mentioned_mr)
@@ -84,14 +84,7 @@ shared_examples 'a mentionable' do
         with(referenced, subject.local_reference, author)
     end
 
-    subject.create_cross_references!(project, author)
-  end
-
-  it 'detects existing cross-references' do
-    SystemNoteService.cross_reference(mentioned_issue, subject.local_reference, author)
-
-    expect(subject).to have_mentioned(mentioned_issue)
-    expect(subject).not_to have_mentioned(mentioned_mr)
+    subject.create_cross_references!
   end
 end
 
@@ -143,6 +136,6 @@ shared_examples 'an editable mentionable' do
     end
 
     set_mentionable_text.call(new_text)
-    subject.create_new_cross_references!(project, author)
+    subject.create_new_cross_references!(author)
   end
 end
diff --git a/spec/support/services_shared_context.rb b/spec/support/services_shared_context.rb
index 4d007ae55ee1391874cb528172d67cb14b9d057a..d1c999cad4de8d2625964478f90b86f6d7b55cd2 100644
--- a/spec/support/services_shared_context.rb
+++ b/spec/support/services_shared_context.rb
@@ -3,7 +3,13 @@ Service.available_services_names.each do |service|
     let(:dashed_service) { service.dasherize }
     let(:service_method) { "#{service}_service".to_sym }
     let(:service_klass) { "#{service}_service".classify.constantize }
-    let(:service_attrs_list) { service_klass.new.fields.inject([]) {|arr, hash| arr << hash[:name].to_sym } }
+    let(:service_fields) { service_klass.new.fields }
+    let(:service_attrs_list) { service_fields.inject([]) {|arr, hash| arr << hash[:name].to_sym } }
+    let(:service_attrs_list_without_passwords) do
+      service_fields.
+        select { |field| field[:type] != 'password' }.
+        map { |field| field[:name].to_sym}
+    end
     let(:service_attrs) do
       service_attrs_list.inject({}) do |hash, k|
         if k =~ /^(token*|.*_token|.*_key)/
diff --git a/tmp/.gitkeep b/tmp/.gitkeep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000