diff --git a/CHANGELOG b/CHANGELOG
index 86f544091c8971907cc6dd080235757a75c6ec1d..14d2572f7420e6fe3bd2866b09eb2991dcb40abc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,8 @@ v 7.4.0
   - Zen mode for wiki and milestones (Robert Schilling)
   - Move Emoji parsing to html-pipeline-gitlab (Robert Schilling)
   - Font Awesome 4.2 integration (Sullivan Senechal)
+  - Add Pushover service integration (Sullivan Senechal)
+  - Add select field type for services options (Sullivan Senechal)
 
 v 7.3.2
   - Fix creating new file via web editor
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index b143dec3a93bba06c258b90589077d21e8b358c7..4c558e137eae8088404fa6c2b51aadb0c95721ad 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -40,7 +40,8 @@ class Projects::ServicesController < Projects::ApplicationController
   def service_params
     params.require(:service).permit(
       :title, :token, :type, :active, :api_key, :subdomain,
-      :room, :recipients, :project_url
+      :room, :recipients, :project_url,
+      :user_key, :device, :priority, :sound
     )
   end
 end
diff --git a/app/models/project.rb b/app/models/project.rb
index d228da192e47e441079f473a74f61c2acef6b0db..44d63d37beeee8511f9605f5b063a52b37adb6bb 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -64,6 +64,7 @@ class Project < ActiveRecord::Base
   has_one :assembla_service, dependent: :destroy
   has_one :gemnasium_service, dependent: :destroy
   has_one :slack_service, dependent: :destroy
+  has_one :pushover_service, dependent: :destroy
   has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
   has_one :forked_from_project, through: :forked_project_link
   # Merge Requests for target project should be removed with it
@@ -311,7 +312,7 @@ class Project < ActiveRecord::Base
   end
 
   def available_services_names
-    %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack)
+    %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack pushover)
   end
 
   def gitlab_ci?
diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f247fde776262e14db640e82eeae796de439d554
--- /dev/null
+++ b/app/models/project_services/pushover_service.rb
@@ -0,0 +1,113 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id         :integer          not null, primary key
+#  type       :string(255)
+#  title      :string(255)
+#  project_id :integer          not null
+#  created_at :datetime
+#  updated_at :datetime
+#  active     :boolean          default(FALSE), not null
+#  properties :text
+#
+
+class PushoverService < Service
+  include HTTParty
+  base_uri 'https://api.pushover.net/1'
+
+  prop_accessor :api_key, :user_key, :device, :priority, :sound
+  validates :api_key, :user_key, :priority, presence: true, if: :activated?
+
+  def title
+    'Pushover'
+  end
+
+  def description
+    'Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop.'
+  end
+
+  def to_param
+    'pushover'
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'api_key', placeholder: 'Your application key' },
+      { type: 'text', name: 'user_key', placeholder: 'Your user key' },
+      { type: 'text', name: 'device', placeholder: 'Leave blank for all active devices' },
+      { type: 'select', name: 'priority', choices:
+        [
+          ['Lowest Priority', -2],
+          ['Low Priority', -1],
+          ['Normal Priority', 0],
+          ['High Priority', 1]
+        ],
+        default_choice: 0
+      },
+      { type: 'select', name: 'sound', choices:
+        [
+          ['Device default sound', nil],
+          ['Pushover (default)', 'pushover'],
+          ['Bike', 'bike'],
+          ['Bugle', 'bugle'],
+          ['Cash Register', 'cashregister'],
+          ['Classical', 'classical'],
+          ['Cosmic', 'cosmic'],
+          ['Falling', 'falling'],
+          ['Gamelan', 'gamelan'],
+          ['Incoming', 'incoming'],
+          ['Intermission', 'intermission'],
+          ['Magic', 'magic'],
+          ['Mechanical', 'mechanical'],
+          ['Piano Bar', 'pianobar'],
+          ['Siren', 'siren'],
+          ['Space Alarm', 'spacealarm'],
+          ['Tug Boat', 'tugboat'],
+          ['Alien Alarm (long)', 'alien'],
+          ['Climb (long)', 'climb'],
+          ['Persistent (long)', 'persistent'],
+          ['Pushover Echo (long)', 'echo'],
+          ['Up Down (long)', 'updown'],
+          ['None (silent)', 'none']
+        ]
+      },
+    ]
+  end
+
+  def execute(push_data)
+    ref = push_data[:ref].gsub('refs/heads/', '')
+    before = push_data[:before]
+    after = push_data[:after]
+
+    if before =~ /000000/
+      message = "#{push_data[:user_name]} pushed new branch \"#{ref}\"."
+    elsif after =~ /000000/
+      message = "#{push_data[:user_name]} deleted branch \"#{ref}\"."
+    else
+      message = "#{push_data[:user_name]} push to branch \"#{ref}\"."
+    end
+
+    if push_data[:total_commits_count] > 0
+      message << "\nTotal commits count: #{push_data[:total_commits_count]}"
+    end
+
+    pushover_data = {
+      token: api_key,
+      user: user_key,
+      device: device,
+      priority: priority,
+      title: "#{project.name_with_namespace}",
+      message: message,
+      url: push_data[:repository][:homepage],
+      url_title: "See project #{project.name_with_namespace}"
+    }
+
+    # Sound parameter MUST NOT be sent to API if not selected
+    if sound
+      pushover_data.merge!(sound: sound)
+    end
+
+    PushoverService.post('/messages.json', body: pushover_data)
+  end
+end
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index a5db7969a68755d8f30b4b886c1ddcb541c96407..16d59d1fe9d6fce4e8fe17555718604d0f5e1236 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -28,8 +28,11 @@
 
   - @service.fields.each do |field|
     - name = field[:name]
+    - value = @service.send(name)
     - type = field[:type]
     - placeholder = field[:placeholder]
+    - choices = field[:choices]
+    - default_choice = field[:default_choice]
 
     .form-group
       = f.label name, class: "control-label"
@@ -40,6 +43,8 @@
           = f.text_area name, rows: 5, class: "form-control", placeholder: placeholder
         - elsif type == 'checkbox'
           = f.check_box name
+        - elsif type == 'select'
+          = f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" }
 
   .form-actions
     = f.submit 'Save', class: 'btn btn-save'
diff --git a/features/project/service.feature b/features/project/service.feature
index a5af065c9e7da2438d0f244208ca7418d516dde9..af88eaefa8f615ef52f27b163bae7c940adc0214 100644
--- a/features/project/service.feature
+++ b/features/project/service.feature
@@ -43,6 +43,12 @@ Feature: Project Services
     And I fill Slack settings
     Then I should see Slack service settings saved
 
+  Scenario: Activate Pushover service
+    When I visit project "Shop" services page
+    And I click Pushover service link
+    And I fill Pushover settings
+    Then I should see Pushover service settings saved
+
   Scenario: Activate email on push service
     When I visit project "Shop" services page
     And I click email on push service link
diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb
index b56b413eac86a662aad7143f7e35ab5b9bc4660c..d816fcafbaaf2ebc18914a1c7a34bbb31f762ae2 100644
--- a/features/steps/project/services.rb
+++ b/features/steps/project/services.rb
@@ -13,6 +13,7 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
     page.should have_content 'Hipchat'
     page.should have_content 'GitLab CI'
     page.should have_content 'Assembla'
+    page.should have_content 'Pushover'
   end
 
   step 'I click gitlab-ci service link' do
@@ -118,4 +119,26 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
     find_field('Room').value.should == '#gitlab'
     find_field('Token').value.should == 'verySecret'
   end
+
+  step 'I click Pushover service link' do
+    click_link 'Pushover'
+  end
+
+  step 'I fill Pushover settings' do
+    check 'Active'
+    fill_in 'Api key', with: 'verySecret'
+    fill_in 'User key', with: 'verySecret'
+    fill_in 'Device', with: 'myDevice'
+    select 'High Priority', from: 'Priority'
+    select 'Bike', from: 'Sound'
+    click_button 'Save'
+  end
+
+  step 'I should see Pushover service settings saved' do
+    find_field('Api key').value.should == 'verySecret'
+    find_field('User key').value.should == 'verySecret'
+    find_field('Device').value.should == 'myDevice'
+    find_field('Priority').find('option[selected]').value.should == '1'
+    find_field('Sound').find('option[selected]').value.should == 'bike'
+  end
 end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 524cab2b9258ec13fefe353e1faa8e629bba68c0..48b58400a1ecfdc54e0bdece8be8da77e3811cb2 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -47,6 +47,7 @@ describe Project do
     it { should have_many(:protected_branches).dependent(:destroy) }
     it { should have_one(:forked_project_link).dependent(:destroy) }
     it { should have_one(:slack_service).dependent(:destroy) }
+    it { should have_one(:pushover_service).dependent(:destroy) }
   end
 
   describe "Mass assignment" do
diff --git a/spec/models/pushover_service_spec.rb b/spec/models/pushover_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..59db69d7572f567cec17b850bcb8c0f6684c9926
--- /dev/null
+++ b/spec/models/pushover_service_spec.rb
@@ -0,0 +1,69 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id         :integer          not null, primary key
+#  type       :string(255)
+#  title      :string(255)
+#  project_id :integer          not null
+#  created_at :datetime
+#  updated_at :datetime
+#  active     :boolean          default(FALSE), not null
+#  properties :text
+#
+
+require 'spec_helper'
+
+describe PushoverService do
+  describe 'Associations' do
+    it { should belong_to :project }
+    it { should have_one :service_hook }
+  end
+
+  describe 'Validations' do
+    context 'active' do
+      before do
+        subject.active = true
+      end
+
+      it { should validate_presence_of :api_key }
+      it { should validate_presence_of :user_key }
+      it { should validate_presence_of :priority }
+    end
+  end
+
+  describe 'Execute' do
+    let(:pushover) { PushoverService.new }
+    let(:user) { create(:user) }
+    let(:project) { create(:project) }
+    let(:sample_data) { GitPushService.new.sample_data(project, user) }
+
+    let(:api_key) { 'verySecret' }
+    let(:user_key) { 'verySecret' }
+    let(:device) { 'myDevice' }
+    let(:priority) { 0 }
+    let(:sound) { 'bike' }
+    let(:api_url) { 'https://api.pushover.net/1/messages.json' }
+
+    before do
+      pushover.stub(
+        project: project,
+        project_id: project.id,
+        service_hook: true,
+        api_key: api_key,
+        user_key: user_key,
+        device: device,
+        priority: priority,
+        sound: sound
+      )
+
+      WebMock.stub_request(:post, api_url)
+    end
+
+    it 'should call Pushover API' do
+      pushover.execute(sample_data)
+
+      WebMock.should have_requested(:post, api_url).once
+    end
+  end
+end