slack_notification_generator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +73 -0
- data/README.md +49 -0
- data/Rakefile +32 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/bin/slack_notification_generator +3 -0
- data/hack.rb +169 -0
- data/lib/slack_notification_generator.rb +1 -0
- data/lib/slack_notification_generator/main.rb +184 -0
- data/slack_notification_generator.gemspec +74 -0
- metadata +158 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: def98cb8feb24e266a4b81691e3de884ce675654
         | 
| 4 | 
            +
              data.tar.gz: 98b0e43749e745fb6014bb1de901802a674f93b2
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 4da777579117a724979de330ce58a2e98c3dc40ee741e047682bfd3731202e64096c55dbfaea6241d0f0fedf36be902fd3f4b4225544d1997258787dae5c5dbc
         | 
| 7 | 
            +
              data.tar.gz: e3f86f7a2eba13c56569d349053f5d1eed7c7b82d4dfc5c68f0b0a25385046625c3a578a1f73cb6c76a03d4d98cfa54434c4cbdb3476571840e46302a5c3c29b
         | 
    
        data/.ruby-gemset
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            slack_notification_generator
         | 
    
        data/.ruby-version
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            2.2.2
         | 
    
        data/CHANGELOG.md
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    | @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            source 'https://rubygems.org'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            gem 'chronic_duration', '~> 0.10'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            group :development do
         | 
| 6 | 
            +
              gem 'yard', '~> 0.8'
         | 
| 7 | 
            +
              gem 'rdoc', '~> 4.1'
         | 
| 8 | 
            +
              gem 'jeweler', '~> 2.0'
         | 
| 9 | 
            +
              gem 'byebug', '~> 5.0'
         | 
| 10 | 
            +
              gem 'awesome_print', '~> 1.6'
         | 
| 11 | 
            +
              gem 'github_changelog_generator', '~> 1.6'
         | 
| 12 | 
            +
            end
         | 
    
        data/Gemfile.lock
    ADDED
    
    | @@ -0,0 +1,73 @@ | |
| 1 | 
            +
            GEM
         | 
| 2 | 
            +
              remote: https://rubygems.org/
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                addressable (2.3.8)
         | 
| 5 | 
            +
                awesome_print (1.6.1)
         | 
| 6 | 
            +
                builder (3.2.2)
         | 
| 7 | 
            +
                byebug (5.0.0)
         | 
| 8 | 
            +
                  columnize (= 0.9.0)
         | 
| 9 | 
            +
                chronic_duration (0.10.6)
         | 
| 10 | 
            +
                  numerizer (~> 0.1.1)
         | 
| 11 | 
            +
                colorize (0.7.7)
         | 
| 12 | 
            +
                columnize (0.9.0)
         | 
| 13 | 
            +
                descendants_tracker (0.0.4)
         | 
| 14 | 
            +
                  thread_safe (~> 0.3, >= 0.3.1)
         | 
| 15 | 
            +
                faraday (0.9.1)
         | 
| 16 | 
            +
                  multipart-post (>= 1.2, < 3)
         | 
| 17 | 
            +
                git (1.2.9.1)
         | 
| 18 | 
            +
                github_api (0.12.4)
         | 
| 19 | 
            +
                  addressable (~> 2.3)
         | 
| 20 | 
            +
                  descendants_tracker (~> 0.0.4)
         | 
| 21 | 
            +
                  faraday (~> 0.8, < 0.10)
         | 
| 22 | 
            +
                  hashie (>= 3.4)
         | 
| 23 | 
            +
                  multi_json (>= 1.7.5, < 2.0)
         | 
| 24 | 
            +
                  nokogiri (~> 1.6.6)
         | 
| 25 | 
            +
                  oauth2
         | 
| 26 | 
            +
                github_changelog_generator (1.8.2)
         | 
| 27 | 
            +
                  colorize (~> 0.7)
         | 
| 28 | 
            +
                  github_api (~> 0.12)
         | 
| 29 | 
            +
                hashie (3.4.2)
         | 
| 30 | 
            +
                highline (1.7.3)
         | 
| 31 | 
            +
                jeweler (2.0.1)
         | 
| 32 | 
            +
                  builder
         | 
| 33 | 
            +
                  bundler (>= 1.0)
         | 
| 34 | 
            +
                  git (>= 1.2.5)
         | 
| 35 | 
            +
                  github_api
         | 
| 36 | 
            +
                  highline (>= 1.6.15)
         | 
| 37 | 
            +
                  nokogiri (>= 1.5.10)
         | 
| 38 | 
            +
                  rake
         | 
| 39 | 
            +
                  rdoc
         | 
| 40 | 
            +
                jwt (1.5.1)
         | 
| 41 | 
            +
                mini_portile (0.6.2)
         | 
| 42 | 
            +
                multi_json (1.11.2)
         | 
| 43 | 
            +
                multi_xml (0.5.5)
         | 
| 44 | 
            +
                multipart-post (2.0.0)
         | 
| 45 | 
            +
                nokogiri (1.6.6.2)
         | 
| 46 | 
            +
                  mini_portile (~> 0.6.0)
         | 
| 47 | 
            +
                numerizer (0.1.1)
         | 
| 48 | 
            +
                oauth2 (1.0.0)
         | 
| 49 | 
            +
                  faraday (>= 0.8, < 0.10)
         | 
| 50 | 
            +
                  jwt (~> 1.0)
         | 
| 51 | 
            +
                  multi_json (~> 1.3)
         | 
| 52 | 
            +
                  multi_xml (~> 0.5)
         | 
| 53 | 
            +
                  rack (~> 1.2)
         | 
| 54 | 
            +
                rack (1.6.4)
         | 
| 55 | 
            +
                rake (10.4.2)
         | 
| 56 | 
            +
                rdoc (4.2.0)
         | 
| 57 | 
            +
                thread_safe (0.3.5)
         | 
| 58 | 
            +
                yard (0.8.7.6)
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            PLATFORMS
         | 
| 61 | 
            +
              ruby
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            DEPENDENCIES
         | 
| 64 | 
            +
              awesome_print (~> 1.6)
         | 
| 65 | 
            +
              byebug (~> 5.0)
         | 
| 66 | 
            +
              chronic_duration (~> 0.10)
         | 
| 67 | 
            +
              github_changelog_generator (~> 1.6)
         | 
| 68 | 
            +
              jeweler (~> 2.0)
         | 
| 69 | 
            +
              rdoc (~> 4.1)
         | 
| 70 | 
            +
              yard (~> 0.8)
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            BUNDLED WITH
         | 
| 73 | 
            +
               1.10.5
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            [](http://badge.fury.io/rb/slack_notification_generator)
         | 
| 2 | 
            +
            [](https://gemnasium.com/jasonhutchens/slack_notification_generator)
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            Slack Notification Generator
         | 
| 5 | 
            +
            ============================
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Sends a notification to a Slack channel to indicate that a branch of your project has just been deployed by your CI system.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            Usage
         | 
| 10 | 
            +
            -----
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            Define the following environments in your CI system.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            * `CI_BRANCH`: the name of the branch being built (such as "develop" or "master")
         | 
| 15 | 
            +
            * `SLACK_HOOK`: the URL Slack gave you when you added the webhook integration (required)
         | 
| 16 | 
            +
            * `SLACK_REPO`: an optional URL to your GitHub repo (for adding links to PRs)
         | 
| 17 | 
            +
            * `SLACK_JIRA`: an optional URL to your JIRA instance (for adding links to issues)
         | 
| 18 | 
            +
            * `SLACK_USER`: the user to post the notification as (defaults to "Notification")
         | 
| 19 | 
            +
            * `SLACK_ICON`: the emoji for the user's avatar (defaults to ":bell:")
         | 
| 20 | 
            +
            * `SLACK_CHAN`: the channel to post the notification to (defaults to "#general")
         | 
| 21 | 
            +
            * `SLACK_NAME`: an optional name for your project
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            When your CI system deploys your project, run:
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ```
         | 
| 26 | 
            +
            $ slack_notification_generator [HEAD]
         | 
| 27 | 
            +
            ```
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            Specify an argument of `HEAD` if you want to generate a notification relative to the latest tag. Otherwise it will be assumed that you want to generate a notification relative to the most recent pair of tags (for example, you may have tagged `master` before triggering a deploy to production).
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            Assumptions
         | 
| 32 | 
            +
            -----------
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            We assume the following:
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            * you practice something like git-flow, with `develop`, `master` and `release` branches
         | 
| 37 | 
            +
            * you use pull requests to merge most of your work to `develop`
         | 
| 38 | 
            +
            * you tag `master` whenever you update production
         | 
| 39 | 
            +
            * you use JIRA, and add JIRA commands to your git messages to link to issues and log time
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            Example
         | 
| 42 | 
            +
            -------
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            (TBD)
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            Copyright
         | 
| 47 | 
            +
            ---------
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            Copyright (c) 2015 Jason Hutchens. See UNLICENSE for further details.
         | 
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'rubygems'
         | 
| 4 | 
            +
            require 'bundler'
         | 
| 5 | 
            +
            begin
         | 
| 6 | 
            +
              Bundler.setup(:default, :development)
         | 
| 7 | 
            +
            rescue Bundler::BundlerError => e
         | 
| 8 | 
            +
              $stderr.puts e.message
         | 
| 9 | 
            +
              $stderr.puts "Run `bundle install` to install missing gems"
         | 
| 10 | 
            +
              exit e.status_code
         | 
| 11 | 
            +
            end
         | 
| 12 | 
            +
            require 'rake'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            require 'jeweler'
         | 
| 15 | 
            +
            Jeweler::Tasks.new do |gem|
         | 
| 16 | 
            +
              # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
         | 
| 17 | 
            +
              gem.name = "slack_notification_generator"
         | 
| 18 | 
            +
              gem.homepage = "http://github.com/JasonHutchens/slack_notification_generator"
         | 
| 19 | 
            +
              gem.license = "UNLICENSE"
         | 
| 20 | 
            +
              gem.summary = %Q{Sends notifications to Slack when your CI system deploys your project.}
         | 
| 21 | 
            +
              gem.description = %Q{Does what it says on the tin.}
         | 
| 22 | 
            +
              gem.email = "jasonhutchens@gmail.com"
         | 
| 23 | 
            +
              gem.authors = ["Jason Hutchens"]
         | 
| 24 | 
            +
              gem.required_ruby_version = "~> 2.2"
         | 
| 25 | 
            +
              # dependencies defined in Gemfile
         | 
| 26 | 
            +
            end
         | 
| 27 | 
            +
            Jeweler::RubygemsDotOrgTasks.new
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            task :default => :clean
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            require 'yard'
         | 
| 32 | 
            +
            YARD::Rake::YardocTask.new
         | 
    
        data/UNLICENSE
    ADDED
    
    | @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            This is free and unencumbered software released into the public domain.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Anyone is free to copy, modify, publish, use, compile, sell, or
         | 
| 4 | 
            +
            distribute this software, either in source code form or as a compiled
         | 
| 5 | 
            +
            binary, for any purpose, commercial or non-commercial, and by any
         | 
| 6 | 
            +
            means.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            In jurisdictions that recognize copyright laws, the author or authors
         | 
| 9 | 
            +
            of this software dedicate any and all copyright interest in the
         | 
| 10 | 
            +
            software to the public domain. We make this dedication for the benefit
         | 
| 11 | 
            +
            of the public at large and to the detriment of our heirs and
         | 
| 12 | 
            +
            successors. We intend this dedication to be an overt act of
         | 
| 13 | 
            +
            relinquishment in perpetuity of all present and future rights to this
         | 
| 14 | 
            +
            software under copyright law.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 17 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 18 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
         | 
| 19 | 
            +
            IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
         | 
| 20 | 
            +
            OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
         | 
| 21 | 
            +
            ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
         | 
| 22 | 
            +
            OTHER DEALINGS IN THE SOFTWARE.
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            For more information, please refer to <http://unlicense.org/>
         | 
    
        data/VERSION
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            0.1.0
         | 
    
        data/hack.rb
    ADDED
    
    | @@ -0,0 +1,169 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'date'
         | 
| 4 | 
            +
            require 'json'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # TODO: fail unless ENV['SLACK_HOOK'] is defined
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            env =
         | 
| 9 | 
            +
              case ENV['CI_BRANCH']
         | 
| 10 | 
            +
              when 'master'
         | 
| 11 | 
            +
                'Production'
         | 
| 12 | 
            +
              when 'develop'
         | 
| 13 | 
            +
                'Staging'
         | 
| 14 | 
            +
              when /^release/
         | 
| 15 | 
            +
                'Release'
         | 
| 16 | 
            +
              else
         | 
| 17 | 
            +
                'Development'
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            changelog = []
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            # get the most recent tag in the current branch
         | 
| 23 | 
            +
            this_tag = 'HEAD'
         | 
| 24 | 
            +
            prev_tag = `git describe --abbrev=0 --tags`.strip
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            # use the previous tag if we've told it to
         | 
| 27 | 
            +
            if false
         | 
| 28 | 
            +
              this_tag = prev_tag
         | 
| 29 | 
            +
              prev_tag = `git describe --abbrev=0 --tags #{this_tag}^`.strip
         | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            def extract_commits(blob)
         | 
| 33 | 
            +
              commits = []
         | 
| 34 | 
            +
              commit = nil
         | 
| 35 | 
            +
              blob.split("\n").map(&:strip).each do |line|
         | 
| 36 | 
            +
                case line
         | 
| 37 | 
            +
                when /^commit ([0-9a-f]+)$/
         | 
| 38 | 
            +
                  commits << commit unless commit.nil?
         | 
| 39 | 
            +
                  commit = { hash: $1[0..6], skip: false }
         | 
| 40 | 
            +
                when /^Author: ([a-zA-Z]+)/
         | 
| 41 | 
            +
                  commit[:author] = $1.downcase
         | 
| 42 | 
            +
                when /^Date: +(.*)$/
         | 
| 43 | 
            +
                  commit[:date] = Date.parse($1)
         | 
| 44 | 
            +
                when /^([A-Z]+-[0-9]+)/
         | 
| 45 | 
            +
                  commit[:issue] = $1
         | 
| 46 | 
            +
                  if line =~ /#time +([0-9][^\s]*)/
         | 
| 47 | 
            +
                    commit[:time] = $1
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                else
         | 
| 50 | 
            +
                  commit[:message] ||= line unless line.empty?
         | 
| 51 | 
            +
                  commit[:skip] = true if line =~ /\[skip ci\]/
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
              commits << commit unless commit.nil?
         | 
| 55 | 
            +
              commits
         | 
| 56 | 
            +
            end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            def add_attachment(store, title, data)
         | 
| 59 | 
            +
              return if data.nil? || data.length == 0
         | 
| 60 | 
            +
              # TODO: use UTF symbol for bullet point
         | 
| 61 | 
            +
              data.map! do |line|
         | 
| 62 | 
            +
                line.split("\n").map(&:strip).join("\n  ")
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
              store <<
         | 
| 65 | 
            +
                {
         | 
| 66 | 
            +
                  title: title,
         | 
| 67 | 
            +
                  text: data.map { |l| "* #{l}" }.join("\n")
         | 
| 68 | 
            +
                }
         | 
| 69 | 
            +
            end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            def format(commit)
         | 
| 72 | 
            +
              commit[:authors] ||= [commit[:author]].compact
         | 
| 73 | 
            +
              commit[:issues] ||= [commit[:issue]].compact
         | 
| 74 | 
            +
              commit[:times] ||= [commit[:time]].compact
         | 
| 75 | 
            +
              link =
         | 
| 76 | 
            +
                if commit[:pull]
         | 
| 77 | 
            +
                  if ENV['SLACK_REPO']
         | 
| 78 | 
            +
                    "<[#{ENV['SLACK_REPO']}/pull/#{commit[:pull]}|##{commit[:pull]}>"
         | 
| 79 | 
            +
                  else
         | 
| 80 | 
            +
                    "##{commit[:pull]}"
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                else
         | 
| 83 | 
            +
                  if ENV['SLACK_REPO']
         | 
| 84 | 
            +
                    "<[#{ENV['SLACK_REPO']}/commit/#{commit[:hash]}|##{commit[:hash]}>"
         | 
| 85 | 
            +
                  else
         | 
| 86 | 
            +
                    "##{commit[:hash]}"
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
              issues =
         | 
| 90 | 
            +
                commit[:issues].map do |issue|
         | 
| 91 | 
            +
                  if ENV['SLACK_JIRA']
         | 
| 92 | 
            +
                    "<[#{ENV['SLACK_JIRA']}/browse/#{issue}|#{issue}"
         | 
| 93 | 
            +
                  else
         | 
| 94 | 
            +
                    issue
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
                end.join(', ')
         | 
| 97 | 
            +
              issues ||= "(no issues)"
         | 
| 98 | 
            +
              time = "(no time)"
         | 
| 99 | 
            +
              <<-eos
         | 
| 100 | 
            +
                #{commit[:date]} #{commit[:message]} (#{link})
         | 
| 101 | 
            +
                #{issues} | #{commit[:authors].join(', ')} | #{time}
         | 
| 102 | 
            +
              eos
         | 
| 103 | 
            +
            end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            commits = []
         | 
| 106 | 
            +
            commit = nil
         | 
| 107 | 
            +
            blob = `git log --merges #{this_tag} ^#{prev_tag}`
         | 
| 108 | 
            +
            blob.split("\n").map(&:strip).each do |line|
         | 
| 109 | 
            +
              case line
         | 
| 110 | 
            +
              when /^commit ([0-9a-f]+)$/
         | 
| 111 | 
            +
                commits << commit unless commit.nil?
         | 
| 112 | 
            +
                commit = { hash: $1[0..6] }
         | 
| 113 | 
            +
              when /^Merge: ([a-f0-9]+) ([a-f0-9]+)/
         | 
| 114 | 
            +
                commit[:range] = ($1..$2)
         | 
| 115 | 
            +
              when /^Author: ([a-zA-Z]+)/
         | 
| 116 | 
            +
              when /^Date: +(.*)$/
         | 
| 117 | 
            +
                commit[:date] = Date.parse($1)
         | 
| 118 | 
            +
              when /^Merge pull request #([0-9]*) /
         | 
| 119 | 
            +
                commit[:pull] = $1
         | 
| 120 | 
            +
              else
         | 
| 121 | 
            +
                commit[:message] ||= line unless line.empty?
         | 
| 122 | 
            +
              end
         | 
| 123 | 
            +
            end
         | 
| 124 | 
            +
            commits << commit unless commit.nil?
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            pull_requests = []
         | 
| 127 | 
            +
            commit_filter = {}
         | 
| 128 | 
            +
            commits.each do |commit|
         | 
| 129 | 
            +
              next unless commit[:pull]
         | 
| 130 | 
            +
              blob = `git log --no-merges #{commit[:range].last} ^#{commit[:range].first}`
         | 
| 131 | 
            +
              commit[:authors] = []
         | 
| 132 | 
            +
              commit[:issues] = []
         | 
| 133 | 
            +
              commit[:times] = []
         | 
| 134 | 
            +
              extract_commits(blob).each do |child|
         | 
| 135 | 
            +
                commit_filter[child[:hash]] = true
         | 
| 136 | 
            +
                commit[:authors] << child[:author]
         | 
| 137 | 
            +
                commit[:issues] << child[:issue] if child[:issue]
         | 
| 138 | 
            +
                commit[:times] << child[:time] if child[:time]
         | 
| 139 | 
            +
              end
         | 
| 140 | 
            +
              commit[:authors].sort!.uniq!
         | 
| 141 | 
            +
              commit[:issues].sort!.uniq!
         | 
| 142 | 
            +
              pull_requests << commit
         | 
| 143 | 
            +
            end
         | 
| 144 | 
            +
            pull_requests.map! { |commit| format(commit) }
         | 
| 145 | 
            +
             | 
| 146 | 
            +
            blob = `git log --no-merges #{this_tag} ^#{prev_tag}`
         | 
| 147 | 
            +
            other_commits = []
         | 
| 148 | 
            +
            extract_commits(blob).each do |commit|
         | 
| 149 | 
            +
              next if commit_filter[commit[:hash]] || commit[:skip]
         | 
| 150 | 
            +
              other_commits << commit
         | 
| 151 | 
            +
            end
         | 
| 152 | 
            +
            other_commits.map! { |commit| format(commit) }
         | 
| 153 | 
            +
             | 
| 154 | 
            +
            attachments = []
         | 
| 155 | 
            +
            add_attachment(attachments, "Pull Requests", pull_requests)
         | 
| 156 | 
            +
            add_attachment(attachments, "Other Commits", other_commits)
         | 
| 157 | 
            +
            exit if attachments.length == 0
         | 
| 158 | 
            +
             | 
| 159 | 
            +
            payload =
         | 
| 160 | 
            +
              {
         | 
| 161 | 
            +
                username: ENV['SLACK_USER'] || 'Notification',
         | 
| 162 | 
            +
                icon_emoji: ENV['SLACK_ICON'] || ':bell:',
         | 
| 163 | 
            +
                channel: ENV['SLACK_CHAN'] || '#general',
         | 
| 164 | 
            +
                text: "*#{[ENV['SLACK_NAME'], env].compact.join(' ')} Release*",
         | 
| 165 | 
            +
                attachments: attachments
         | 
| 166 | 
            +
              }
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            # submit payload to Slack
         | 
| 169 | 
            +
            puts payload.to_json
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            require 'slack_notification_generator/main'
         | 
| @@ -0,0 +1,184 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'chronic_duration'
         | 
| 4 | 
            +
            require 'date'
         | 
| 5 | 
            +
            require 'json'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            unless ENV['SLACK_HOOK']
         | 
| 8 | 
            +
              puts 'you must define the "SLACK_HOOK" environment variable'
         | 
| 9 | 
            +
              exit 1
         | 
| 10 | 
            +
            end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            env =
         | 
| 13 | 
            +
              case ENV['CI_BRANCH']
         | 
| 14 | 
            +
              when 'master'
         | 
| 15 | 
            +
                'Production'
         | 
| 16 | 
            +
              when 'develop'
         | 
| 17 | 
            +
                'Staging'
         | 
| 18 | 
            +
              when /^release/
         | 
| 19 | 
            +
                'Release'
         | 
| 20 | 
            +
              else
         | 
| 21 | 
            +
                'Development'
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            changelog = []
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            this_tag = 'HEAD'
         | 
| 27 | 
            +
            prev_tag = `git describe --abbrev=0 --tags`.strip
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            unless ARGV[0] == "HEAD"
         | 
| 30 | 
            +
              this_tag = prev_tag
         | 
| 31 | 
            +
              prev_tag = `git describe --abbrev=0 --tags #{this_tag}^`.strip
         | 
| 32 | 
            +
            end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            def extract_commits(blob)
         | 
| 35 | 
            +
              commits = []
         | 
| 36 | 
            +
              commit = nil
         | 
| 37 | 
            +
              blob.split("\n").map(&:strip).each do |line|
         | 
| 38 | 
            +
                case line
         | 
| 39 | 
            +
                when /^commit ([0-9a-f]+)$/
         | 
| 40 | 
            +
                  commits << commit unless commit.nil?
         | 
| 41 | 
            +
                  commit = { hash: $1[0..6], skip: false }
         | 
| 42 | 
            +
                when /^Author: ([a-zA-Z]+)/
         | 
| 43 | 
            +
                  commit[:author] = $1.downcase
         | 
| 44 | 
            +
                when /^Date: +(.*)$/
         | 
| 45 | 
            +
                  commit[:date] = Date.parse($1)
         | 
| 46 | 
            +
                when /^([A-Z]+-[0-9]+)/
         | 
| 47 | 
            +
                  commit[:issue] = $1
         | 
| 48 | 
            +
                  if line =~ /#time +([0-9][^\s]*)/
         | 
| 49 | 
            +
                    commit[:time] = $1
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                else
         | 
| 52 | 
            +
                  commit[:message] ||= line unless line.empty?
         | 
| 53 | 
            +
                  commit[:skip] = true if line =~ /\[skip ci\]/
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
              commits << commit unless commit.nil?
         | 
| 57 | 
            +
              commits
         | 
| 58 | 
            +
            end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            def add_attachment(store, title, data)
         | 
| 61 | 
            +
              return if data.nil? || data.length == 0
         | 
| 62 | 
            +
              data.map! do |line|
         | 
| 63 | 
            +
                line.split("\n").map(&:strip).join("\n  ")
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
              store <<
         | 
| 66 | 
            +
                {
         | 
| 67 | 
            +
                  title: title,
         | 
| 68 | 
            +
                  text: data.map { |l| "• #{l}" }.join("\n")
         | 
| 69 | 
            +
                }
         | 
| 70 | 
            +
            end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            def format(commit)
         | 
| 73 | 
            +
              commit[:authors] ||= [commit[:author]].compact
         | 
| 74 | 
            +
              commit[:issues] ||= [commit[:issue]].compact
         | 
| 75 | 
            +
              commit[:times] ||= [commit[:time]].compact
         | 
| 76 | 
            +
              link =
         | 
| 77 | 
            +
                if commit[:pull]
         | 
| 78 | 
            +
                  if ENV['SLACK_REPO']
         | 
| 79 | 
            +
                    "<#{ENV['SLACK_REPO']}/pull/#{commit[:pull]}|##{commit[:pull]}>"
         | 
| 80 | 
            +
                  else
         | 
| 81 | 
            +
                    "##{commit[:pull]}"
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                else
         | 
| 84 | 
            +
                  if ENV['SLACK_REPO']
         | 
| 85 | 
            +
                    "<#{ENV['SLACK_REPO']}/commit/#{commit[:hash]}|##{commit[:hash]}>"
         | 
| 86 | 
            +
                  else
         | 
| 87 | 
            +
                    "##{commit[:hash]}"
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
              issues =
         | 
| 91 | 
            +
                if commit[:issues].empty?
         | 
| 92 | 
            +
                  nil
         | 
| 93 | 
            +
                else
         | 
| 94 | 
            +
                  commit[:issues].map do |issue|
         | 
| 95 | 
            +
                    if ENV['SLACK_JIRA']
         | 
| 96 | 
            +
                      "<#{ENV['SLACK_JIRA']}/browse/#{issue}|#{issue}>"
         | 
| 97 | 
            +
                    else
         | 
| 98 | 
            +
                      issue
         | 
| 99 | 
            +
                    end
         | 
| 100 | 
            +
                  end.join(', ')
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
              time =
         | 
| 103 | 
            +
                if commit[:times].empty?
         | 
| 104 | 
            +
                  nil
         | 
| 105 | 
            +
                else
         | 
| 106 | 
            +
                  seconds =
         | 
| 107 | 
            +
                    commit[:times].map do |data|
         | 
| 108 | 
            +
                      ChronicDuration.parse(data)
         | 
| 109 | 
            +
                    end.reduce(:+)
         | 
| 110 | 
            +
                  ChronicDuration.output(seconds)
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
              extras = [issues, commit[:authors].join(', '), time].compact.join(', ')
         | 
| 113 | 
            +
              if commit[:message].length > 50
         | 
| 114 | 
            +
                commit[:message] = commit[:message][0, 47] + "..."
         | 
| 115 | 
            +
              end
         | 
| 116 | 
            +
              <<-eos
         | 
| 117 | 
            +
                #{link} #{commit[:message]} [#{extras}]
         | 
| 118 | 
            +
              eos
         | 
| 119 | 
            +
            end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            commits = []
         | 
| 122 | 
            +
            commit = nil
         | 
| 123 | 
            +
            blob = `git log --merges #{this_tag} ^#{prev_tag}`
         | 
| 124 | 
            +
            blob.split("\n").map(&:strip).each do |line|
         | 
| 125 | 
            +
              case line
         | 
| 126 | 
            +
              when /^commit ([0-9a-f]+)$/
         | 
| 127 | 
            +
                commits << commit unless commit.nil?
         | 
| 128 | 
            +
                commit = { hash: $1[0..6] }
         | 
| 129 | 
            +
              when /^Merge: ([a-f0-9]+) ([a-f0-9]+)/
         | 
| 130 | 
            +
                commit[:range] = ($1..$2)
         | 
| 131 | 
            +
              when /^Author: ([a-zA-Z]+)/
         | 
| 132 | 
            +
              when /^Date: +(.*)$/
         | 
| 133 | 
            +
                commit[:date] = Date.parse($1)
         | 
| 134 | 
            +
              when /^Merge pull request #([0-9]*) /
         | 
| 135 | 
            +
                commit[:pull] = $1
         | 
| 136 | 
            +
              else
         | 
| 137 | 
            +
                commit[:message] ||= line unless line.empty?
         | 
| 138 | 
            +
              end
         | 
| 139 | 
            +
            end
         | 
| 140 | 
            +
            commits << commit unless commit.nil?
         | 
| 141 | 
            +
             | 
| 142 | 
            +
            pull_requests = []
         | 
| 143 | 
            +
            commit_filter = {}
         | 
| 144 | 
            +
            commits.each do |commit|
         | 
| 145 | 
            +
              next unless commit[:pull]
         | 
| 146 | 
            +
              blob = `git log --no-merges #{commit[:range].last} ^#{commit[:range].first}`
         | 
| 147 | 
            +
              commit[:authors] = []
         | 
| 148 | 
            +
              commit[:issues] = []
         | 
| 149 | 
            +
              commit[:times] = []
         | 
| 150 | 
            +
              extract_commits(blob).each do |child|
         | 
| 151 | 
            +
                commit_filter[child[:hash]] = true
         | 
| 152 | 
            +
                commit[:authors] << child[:author]
         | 
| 153 | 
            +
                commit[:issues] << child[:issue] if child[:issue]
         | 
| 154 | 
            +
                commit[:times] << child[:time] if child[:time]
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
              commit[:authors].sort!.uniq!
         | 
| 157 | 
            +
              commit[:issues].sort!.uniq!
         | 
| 158 | 
            +
              pull_requests << commit
         | 
| 159 | 
            +
            end
         | 
| 160 | 
            +
            pull_requests.map! { |commit| format(commit) }
         | 
| 161 | 
            +
             | 
| 162 | 
            +
            blob = `git log --no-merges #{this_tag} ^#{prev_tag}`
         | 
| 163 | 
            +
            other_commits = []
         | 
| 164 | 
            +
            extract_commits(blob).each do |commit|
         | 
| 165 | 
            +
              next if commit_filter[commit[:hash]] || commit[:skip]
         | 
| 166 | 
            +
              other_commits << commit
         | 
| 167 | 
            +
            end
         | 
| 168 | 
            +
            other_commits.map! { |commit| format(commit) }
         | 
| 169 | 
            +
             | 
| 170 | 
            +
            attachments = []
         | 
| 171 | 
            +
            add_attachment(attachments, "Pull Requests", pull_requests)
         | 
| 172 | 
            +
            add_attachment(attachments, "Other Commits", other_commits)
         | 
| 173 | 
            +
            exit if attachments.length == 0
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            payload =
         | 
| 176 | 
            +
              {
         | 
| 177 | 
            +
                username: ENV['SLACK_USER'] || 'Notification',
         | 
| 178 | 
            +
                icon_emoji: ENV['SLACK_ICON'] || ':bell:',
         | 
| 179 | 
            +
                channel: ENV['SLACK_CHAN'] || '#general',
         | 
| 180 | 
            +
                text: "*#{[ENV['SLACK_NAME'], env].compact.join(' ')} Release*",
         | 
| 181 | 
            +
                attachments: attachments
         | 
| 182 | 
            +
              }
         | 
| 183 | 
            +
             | 
| 184 | 
            +
            `curl -X POST --data-urlencode 'payload=#{payload.to_json}' #{ENV['SLACK_HOOK']}`
         | 
| @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            # Generated by jeweler
         | 
| 2 | 
            +
            # DO NOT EDIT THIS FILE DIRECTLY
         | 
| 3 | 
            +
            # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
         | 
| 4 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 5 | 
            +
            # stub: slack_notification_generator 0.1.0 ruby lib
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Gem::Specification.new do |s|
         | 
| 8 | 
            +
              s.name = "slack_notification_generator"
         | 
| 9 | 
            +
              s.version = "0.1.0"
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 12 | 
            +
              s.require_paths = ["lib"]
         | 
| 13 | 
            +
              s.authors = ["Jason Hutchens"]
         | 
| 14 | 
            +
              s.date = "2015-08-29"
         | 
| 15 | 
            +
              s.description = "Does what it says on the tin."
         | 
| 16 | 
            +
              s.email = "jasonhutchens@gmail.com"
         | 
| 17 | 
            +
              s.executables = ["slack_notification_generator"]
         | 
| 18 | 
            +
              s.extra_rdoc_files = [
         | 
| 19 | 
            +
                "CHANGELOG.md",
         | 
| 20 | 
            +
                "README.md"
         | 
| 21 | 
            +
              ]
         | 
| 22 | 
            +
              s.files = [
         | 
| 23 | 
            +
                ".ruby-gemset",
         | 
| 24 | 
            +
                ".ruby-version",
         | 
| 25 | 
            +
                "CHANGELOG.md",
         | 
| 26 | 
            +
                "Gemfile",
         | 
| 27 | 
            +
                "Gemfile.lock",
         | 
| 28 | 
            +
                "README.md",
         | 
| 29 | 
            +
                "Rakefile",
         | 
| 30 | 
            +
                "UNLICENSE",
         | 
| 31 | 
            +
                "VERSION",
         | 
| 32 | 
            +
                "bin/slack_notification_generator",
         | 
| 33 | 
            +
                "hack.rb",
         | 
| 34 | 
            +
                "lib/slack_notification_generator.rb",
         | 
| 35 | 
            +
                "lib/slack_notification_generator/main.rb",
         | 
| 36 | 
            +
                "slack_notification_generator.gemspec"
         | 
| 37 | 
            +
              ]
         | 
| 38 | 
            +
              s.homepage = "http://github.com/JasonHutchens/slack_notification_generator"
         | 
| 39 | 
            +
              s.licenses = ["UNLICENSE"]
         | 
| 40 | 
            +
              s.required_ruby_version = Gem::Requirement.new("~> 2.2")
         | 
| 41 | 
            +
              s.rubygems_version = "2.4.8"
         | 
| 42 | 
            +
              s.summary = "Sends notifications to Slack when your CI system deploys your project."
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              if s.respond_to? :specification_version then
         | 
| 45 | 
            +
                s.specification_version = 4
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
         | 
| 48 | 
            +
                  s.add_runtime_dependency(%q<chronic_duration>, ["~> 0.10"])
         | 
| 49 | 
            +
                  s.add_development_dependency(%q<yard>, ["~> 0.8"])
         | 
| 50 | 
            +
                  s.add_development_dependency(%q<rdoc>, ["~> 4.1"])
         | 
| 51 | 
            +
                  s.add_development_dependency(%q<jeweler>, ["~> 2.0"])
         | 
| 52 | 
            +
                  s.add_development_dependency(%q<byebug>, ["~> 5.0"])
         | 
| 53 | 
            +
                  s.add_development_dependency(%q<awesome_print>, ["~> 1.6"])
         | 
| 54 | 
            +
                  s.add_development_dependency(%q<github_changelog_generator>, ["~> 1.6"])
         | 
| 55 | 
            +
                else
         | 
| 56 | 
            +
                  s.add_dependency(%q<chronic_duration>, ["~> 0.10"])
         | 
| 57 | 
            +
                  s.add_dependency(%q<yard>, ["~> 0.8"])
         | 
| 58 | 
            +
                  s.add_dependency(%q<rdoc>, ["~> 4.1"])
         | 
| 59 | 
            +
                  s.add_dependency(%q<jeweler>, ["~> 2.0"])
         | 
| 60 | 
            +
                  s.add_dependency(%q<byebug>, ["~> 5.0"])
         | 
| 61 | 
            +
                  s.add_dependency(%q<awesome_print>, ["~> 1.6"])
         | 
| 62 | 
            +
                  s.add_dependency(%q<github_changelog_generator>, ["~> 1.6"])
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
              else
         | 
| 65 | 
            +
                s.add_dependency(%q<chronic_duration>, ["~> 0.10"])
         | 
| 66 | 
            +
                s.add_dependency(%q<yard>, ["~> 0.8"])
         | 
| 67 | 
            +
                s.add_dependency(%q<rdoc>, ["~> 4.1"])
         | 
| 68 | 
            +
                s.add_dependency(%q<jeweler>, ["~> 2.0"])
         | 
| 69 | 
            +
                s.add_dependency(%q<byebug>, ["~> 5.0"])
         | 
| 70 | 
            +
                s.add_dependency(%q<awesome_print>, ["~> 1.6"])
         | 
| 71 | 
            +
                s.add_dependency(%q<github_changelog_generator>, ["~> 1.6"])
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
            end
         | 
| 74 | 
            +
             | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,158 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: slack_notification_generator
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Jason Hutchens
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2015-08-29 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: chronic_duration
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '0.10'
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '0.10'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: yard
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '0.8'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '0.8'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: rdoc
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - "~>"
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '4.1'
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - "~>"
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '4.1'
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: jeweler
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - "~>"
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '2.0'
         | 
| 62 | 
            +
              type: :development
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - "~>"
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: '2.0'
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            +
              name: byebug
         | 
| 71 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            +
                requirements:
         | 
| 73 | 
            +
                - - "~>"
         | 
| 74 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            +
                    version: '5.0'
         | 
| 76 | 
            +
              type: :development
         | 
| 77 | 
            +
              prerelease: false
         | 
| 78 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 | 
            +
                requirements:
         | 
| 80 | 
            +
                - - "~>"
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            +
                    version: '5.0'
         | 
| 83 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 84 | 
            +
              name: awesome_print
         | 
| 85 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 86 | 
            +
                requirements:
         | 
| 87 | 
            +
                - - "~>"
         | 
| 88 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 89 | 
            +
                    version: '1.6'
         | 
| 90 | 
            +
              type: :development
         | 
| 91 | 
            +
              prerelease: false
         | 
| 92 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 93 | 
            +
                requirements:
         | 
| 94 | 
            +
                - - "~>"
         | 
| 95 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 96 | 
            +
                    version: '1.6'
         | 
| 97 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 98 | 
            +
              name: github_changelog_generator
         | 
| 99 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 | 
            +
                requirements:
         | 
| 101 | 
            +
                - - "~>"
         | 
| 102 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            +
                    version: '1.6'
         | 
| 104 | 
            +
              type: :development
         | 
| 105 | 
            +
              prerelease: false
         | 
| 106 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 | 
            +
                requirements:
         | 
| 108 | 
            +
                - - "~>"
         | 
| 109 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 110 | 
            +
                    version: '1.6'
         | 
| 111 | 
            +
            description: Does what it says on the tin.
         | 
| 112 | 
            +
            email: jasonhutchens@gmail.com
         | 
| 113 | 
            +
            executables:
         | 
| 114 | 
            +
            - slack_notification_generator
         | 
| 115 | 
            +
            extensions: []
         | 
| 116 | 
            +
            extra_rdoc_files:
         | 
| 117 | 
            +
            - CHANGELOG.md
         | 
| 118 | 
            +
            - README.md
         | 
| 119 | 
            +
            files:
         | 
| 120 | 
            +
            - ".ruby-gemset"
         | 
| 121 | 
            +
            - ".ruby-version"
         | 
| 122 | 
            +
            - CHANGELOG.md
         | 
| 123 | 
            +
            - Gemfile
         | 
| 124 | 
            +
            - Gemfile.lock
         | 
| 125 | 
            +
            - README.md
         | 
| 126 | 
            +
            - Rakefile
         | 
| 127 | 
            +
            - UNLICENSE
         | 
| 128 | 
            +
            - VERSION
         | 
| 129 | 
            +
            - bin/slack_notification_generator
         | 
| 130 | 
            +
            - hack.rb
         | 
| 131 | 
            +
            - lib/slack_notification_generator.rb
         | 
| 132 | 
            +
            - lib/slack_notification_generator/main.rb
         | 
| 133 | 
            +
            - slack_notification_generator.gemspec
         | 
| 134 | 
            +
            homepage: http://github.com/JasonHutchens/slack_notification_generator
         | 
| 135 | 
            +
            licenses:
         | 
| 136 | 
            +
            - UNLICENSE
         | 
| 137 | 
            +
            metadata: {}
         | 
| 138 | 
            +
            post_install_message: 
         | 
| 139 | 
            +
            rdoc_options: []
         | 
| 140 | 
            +
            require_paths:
         | 
| 141 | 
            +
            - lib
         | 
| 142 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 143 | 
            +
              requirements:
         | 
| 144 | 
            +
              - - "~>"
         | 
| 145 | 
            +
                - !ruby/object:Gem::Version
         | 
| 146 | 
            +
                  version: '2.2'
         | 
| 147 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 148 | 
            +
              requirements:
         | 
| 149 | 
            +
              - - ">="
         | 
| 150 | 
            +
                - !ruby/object:Gem::Version
         | 
| 151 | 
            +
                  version: '0'
         | 
| 152 | 
            +
            requirements: []
         | 
| 153 | 
            +
            rubyforge_project: 
         | 
| 154 | 
            +
            rubygems_version: 2.4.8
         | 
| 155 | 
            +
            signing_key: 
         | 
| 156 | 
            +
            specification_version: 4
         | 
| 157 | 
            +
            summary: Sends notifications to Slack when your CI system deploys your project.
         | 
| 158 | 
            +
            test_files: []
         |