diff --git a/CHANGELOG b/CHANGELOG
index 87baa6b66217813ae67a044c7d149ea885df64fb..07ff3d6de4220bb4d3d5d965d516014f258dd90f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -18,6 +18,7 @@ v 8.1.0 (unreleased)
   - 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)
@@ -27,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)
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/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/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/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/ci/build.rb b/app/models/ci/build.rb
index cfafbf6786e025b3862358dfdc2d976a67ac2786..5f8d44148cadc3152a49c87e290214f5426e58fc 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -119,7 +119,7 @@ module Ci
     end
 
     def variables
-      yaml_variables + project_variables + trigger_variables
+      predefined_variables + yaml_variables + project_variables + trigger_variables
     end
 
     def project
@@ -231,6 +231,18 @@ module Ci
       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
@@ -258,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/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_status.rb b/app/models/commit_status.rb
index b4d91b1b0c321b7c16793d32d20c7f4c24a2a3c1..92905c618ebcd2985529ee60ae4e5fefdd625847 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -88,4 +88,8 @@ class CommitStatus < ActiveRecord::Base
   def retry_url
     nil
   end
+
+  def show_warning?
+    false
+  end
 end
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index ad432144bd9ccc9fce4dddd3d83689211e6a9ca9..25da102ba4c47805ccaffeef2b041ca9ebc073e7 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -43,67 +43,57 @@ 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)
-  end
-
-  def mentioned_users(current_user = nil, load_lazy_references: true)
-    # TODO: Douwe: Will be simplified when the "Simplify ..." MR is merged.
+  def all_references(current_user = self.author, text = nil, load_lazy_references: true)
     ext = Gitlab::ReferenceExtractor.new(self.project, current_user, load_lazy_references: load_lazy_references)
-    self.class.mentionable_attrs.each do |attr, options|
-      text = send(attr)
-      cache_key = [self, attr] if options[:cache]
-      ext.analyze(text, cache_key: cache_key, pipeline: options[:pipeline])
-    end
-    ext.users
-  end
-
-  # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference.
-  def references(p = project, current_user = self.author, text = nil, load_lazy_references: true)
-    return [] if text.blank?
-
-    ext = Gitlab::ReferenceExtractor.new(p, current_user, load_lazy_references: load_lazy_references)
-
+    
     if text
       ext.analyze(text)
     else
       self.class.mentionable_attrs.each do |attr, options|
         text = send(attr)
-        cache_key = [self, attr] if options[:cache]
-        ext.analyze(text, cache_key: cache_key)
+        options[:cache_key] = [self, attr] if options.delete(:cache)
+        ext.analyze(text, options)
       end
     end
 
-    (ext.issues + ext.merge_requests + ext.commits) - [local_reference]
+    ext
   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 mentioned_users(current_user = nil, load_lazy_references: true)
+    all_references(current_user).users
+  end
+
+  # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference.
+  def referenced_mentionables(current_user = self.author, text = nil)
+    refs = all_references(current_user, text)
+    (refs.issues + refs.merge_requests + refs.commits) - [local_reference]
+  end
 
+  # Create a cross-reference Note for each GFM reference to another Mentionable found in the +mentionable_attrs+.
+  def create_cross_references!(author = self.author, without = [], text = nil)
+    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
@@ -125,4 +115,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 0888de62f0a5d3f5ff330fd6d075a3f39ae68e69..f5f973c0e698ca36d6f16455523fb8bc626538c8 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -37,7 +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, load_lazy_references: true)
+<<<<<<< HEAD
+  def participants(current_user = self.author, load_lazy_references: true)
     participants = self.class.participant_attrs.flat_map do |attr|
       value =
         if attr.respond_to?(:call)
@@ -46,16 +47,14 @@ module Participable
           send(attr)
         end
 
-      participants_for(value, current_user, project)
+      participants_for(value, current_user)
     end.compact.uniq
 
     if load_lazy_references
       participants = Gitlab::Markdown::ReferenceFilter::LazyReference.load(participants).uniq
 
-      if project
-        participants.select! do |user|
-          user.can?(:read_project, project)
-        end
+      participants.select! do |user|
+        user.can?(:read_project, project)
       end
     end
 
@@ -64,14 +63,14 @@ module Participable
 
   private
 
-  def participants_for(value, current_user = nil, project = nil)
+  def participants_for(value, current_user = nil)
     case value
     when User, Gitlab::Markdown::ReferenceFilter::LazyReference
       [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, load_lazy_references: false)
+      value.participants(current_user, load_lazy_references: false)
     end
   end
 end
diff --git a/app/models/note.rb b/app/models/note.rb
index b4d6ddba703c92cb921bbfc8d604a45a6a12f00b..96cacd667c17a3e61950fbeab327e78a7567ce4a 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/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/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/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/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index 9c3ae622b728bd28f51fc63c991f67b1b47b4b39..91c1b16c9f69064df91e71739628440cae1ec31b 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -25,7 +25,7 @@
           %a
             Build ##{@build.id}
             &middot;
-            %i.fa.fa-warning-sign
+            %i.fa.fa-warning
             This build was retried.
 
   .gray-content-block.second-block
@@ -39,6 +39,27 @@
         .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
diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml
index 7314f8e79d3ad3771f7778d0ceb078430ef06ce8..637154f56aa1d00c6562e99a9c1f811312bf940a 100644
--- a/app/views/projects/commit_statuses/_commit_status.html.haml
+++ b/app/views/projects/commit_statuses/_commit_status.html.haml
@@ -9,6 +9,9 @@
     - else
       %strong Build ##{commit_status.id}
 
+    - if commit_status.show_warning?
+      %i.fa.fa-warning.text-warning
+
   %td
     = commit_status.ref
 
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/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/models/build_spec.rb b/spec/models/build_spec.rb
index d875015b9913b2c259a2dc49484a99f9c44e9222..7f5abb83ac2298813e596c95468be60fc16dbfc8 100644
--- a/spec/models/build_spec.rb
+++ b/spec/models/build_spec.rb
@@ -200,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
@@ -219,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 }
@@ -229,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
@@ -273,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/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/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/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/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/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/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/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb
index 2b52b4c9b10741720b6f333afaed4ef985a57ec4..3bb568f4d494858c432f259cf37c20ef7465f535 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) }
@@ -67,7 +67,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)
@@ -86,14 +86,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
 
@@ -145,6 +138,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