diff --git a/CHANGELOG b/CHANGELOG
index 7eb6ab81dd947ebc57834d18d7bfb11e38fe12b0..7ec1dabcf95af393be2a5f89d547acf44dc05db0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,7 @@ v 8.0.0 (unreleased)
   - Allow configuration of import sources for new projects (Artem Sidorenko)
   - Search for comments should be case insensetive
   - Create cross-reference for closing references on commits pushed to non-default branches (Maƫl Valais)
+  - Ability to search milestones
 
 v 7.14.0
   - Fix bug where non-project members of the target project could set labels on new merge requests.
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 4e2ea6c5710ff14cca8c75d7f5f764d7b3410cc3..eb0408a95e58c3b64349ebdcf8d2633b0303082f 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -23,7 +23,7 @@ class SearchController < ApplicationController
 
     @search_results =
       if @project
-        unless %w(blobs notes issues merge_requests wiki_blobs).
+        unless %w(blobs notes issues merge_requests milestones wiki_blobs).
           include?(@scope)
           @scope = 'blobs'
         end
@@ -36,7 +36,7 @@ class SearchController < ApplicationController
 
         Search::SnippetService.new(current_user, params).execute
       else
-        unless %w(projects issues merge_requests).include?(@scope)
+        unless %w(projects issues merge_requests milestones).include?(@scope)
           @scope = 'projects'
         end
         Search::GlobalService.new(current_user, params).execute
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index d28f3c8d3f908756cfa196c2a76cbe3da1317f8a..c6aff6f709f348fdff95537f18d14113856233cb 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -47,6 +47,13 @@ class Milestone < ActiveRecord::Base
     state :active
   end
 
+  class << self
+    def search(query)
+      query = "%#{query}%"
+      where("title like ? or description like ?", query, query)
+    end
+  end
+
   def expired?
     if due_date
       due_date.past?
@@ -54,7 +61,7 @@ class Milestone < ActiveRecord::Base
       false
     end
   end
-
+  
   def open_items_count
     self.issues.opened.count + self.merge_requests.opened.count
   end
diff --git a/app/views/search/_category.html.haml b/app/views/search/_category.html.haml
index 154332cb9a9d8623391174eebdf5db2ce006483f..a75cd7bd8096e7286af0aef5b77891342b564104 100644
--- a/app/views/search/_category.html.haml
+++ b/app/views/search/_category.html.haml
@@ -21,6 +21,13 @@
           Merge requests
           %span.badge
             = @search_results.merge_requests_count
+    %li{class: ("active" if @scope == 'milestones')}
+      = link_to search_filter_path(scope: 'milestones') do
+        = icon('clock-o fw')
+        %span
+          Milestones
+          %span.badge
+            = @search_results.milestones_count
     %li{class: ("active" if @scope == 'notes')}
       = link_to search_filter_path(scope: 'notes') do
         = icon('comments fw')
@@ -74,4 +81,11 @@
           Merge requests
           %span.badge
             = @search_results.merge_requests_count
+    %li{class: ("active" if @scope == 'milestones')}
+      = link_to search_filter_path(scope: 'milestones') do
+        = icon('clock-o fw')
+        %span
+          Milestones
+          %span.badge
+            = @search_results.milestones_count
 
diff --git a/app/views/search/results/_milestone.html.haml b/app/views/search/results/_milestone.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..e0b18733d742e6319cb25d900eb0384cff15e1e5
--- /dev/null
+++ b/app/views/search/results/_milestone.html.haml
@@ -0,0 +1,9 @@
+.search-result-row
+  %h4
+    = link_to [milestone.project.namespace.becomes(Namespace), milestone.project, milestone] do
+      %span.term.str-truncated= milestone.title
+
+  - if milestone.description.present?
+    .description.term
+      = preserve do
+        = search_md_sanitize(markdown(milestone.description))
\ No newline at end of file
diff --git a/features/search.feature b/features/search.feature
index 1608e8246717a178fdf6f291670062ed8576b53f..a9234c1a611bd254f578b5199a561860594a0d04 100644
--- a/features/search.feature
+++ b/features/search.feature
@@ -23,6 +23,13 @@ Feature: Search
     Then I should see "Foo" link in the search results
     And I should not see "Bar" link in the search results
 
+  Scenario: I should see milestones I am looking for
+    And project has milestones
+    When I search for "Foo"
+    When I click "Milestones" link
+    Then I should see "Foo" link in the search results
+    And I should not see "Bar" link in the search results
+
   Scenario: I should see project code I am looking for
     When I click project "Shop" link
     And I search for "rspec"
@@ -44,6 +51,14 @@ Feature: Search
     Then I should see "Foo" link in the search results
     And I should not see "Bar" link in the search results
 
+  Scenario: I should see project milestones
+    And project has milestones
+    When I click project "Shop" link
+    And I search for "Foo"
+    And I click "Milestones" link
+    Then I should see "Foo" link in the search results
+    And I should not see "Bar" link in the search results
+
   Scenario: I should see Wiki blobs
     And project has Wiki content
     When I click project "Shop" link
diff --git a/features/steps/search.rb b/features/steps/search.rb
index 87893aa02057b6715325efe463be8e20cedab151..79273cbad9a8f4ac6dd1e24c38070659dfc8eb58 100644
--- a/features/steps/search.rb
+++ b/features/steps/search.rb
@@ -41,6 +41,12 @@ class Spinach::Features::Search < Spinach::FeatureSteps
     end
   end
 
+  step 'I click "Milestones" link' do
+    page.within '.search-filter' do
+      click_link 'Milestones'
+    end
+  end
+
   step 'I click "Wiki" link' do
     page.within '.search-filter' do
       click_link 'Wiki'
@@ -72,6 +78,11 @@ class Spinach::Features::Search < Spinach::FeatureSteps
     create(:merge_request, :simple, title: "Bar", source_project: project, target_project: project)
   end
 
+  step 'project has milestones' do
+    create(:milestone, title: "Foo", project: project)
+    create(:milestone, title: "Bar", project: project)
+  end
+
   step 'I should see "Foo" link in the search results' do
     page.within('.results') do
       find(:css, '.search-results').should have_link 'Foo'
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
index 06245374bc8b969c76fc2c2d2aec9c556080419a..2ab2d4af797d5b09451315cb2a38c753cd4d9390 100644
--- a/lib/gitlab/search_results.rb
+++ b/lib/gitlab/search_results.rb
@@ -19,13 +19,15 @@ module Gitlab
         issues.page(page).per(per_page)
       when 'merge_requests'
         merge_requests.page(page).per(per_page)
+      when 'milestones'
+        milestones.page(page).per(per_page)
       else
         Kaminari.paginate_array([]).page(page).per(per_page)
       end
     end
 
     def total_count
-      @total_count ||= projects_count + issues_count + merge_requests_count
+      @total_count ||= projects_count + issues_count + merge_requests_count + milestones_count
     end
 
     def projects_count
@@ -40,6 +42,10 @@ module Gitlab
       @merge_requests_count ||= merge_requests.count
     end
 
+    def milestones_count
+      @milestones_count ||= milestones.count
+    end
+
     def empty?
       total_count.zero?
     end
@@ -60,6 +66,12 @@ module Gitlab
       issues.order('updated_at DESC')
     end
 
+    def milestones
+      milestones = Milestone.where(project_id: limit_project_ids)
+      milestones = milestones.search(query)
+      milestones.order('updated_at DESC')
+    end
+
     def merge_requests
       merge_requests = MergeRequest.in_projects(limit_project_ids)
       if query =~ /[#!](\d+)\z/