slackistrano 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c2221a5e8c65f2a1a082d139cc9cdaf7bb266285
4
- data.tar.gz: f6b272f31ed0920fb37c1df17830c2908b7f3631
3
+ metadata.gz: 95795f6130f67bf6c4845feace7deaa858fb042d
4
+ data.tar.gz: eb3cb8e5d6ecbf13633896090d9ab6831ff05b0b
5
5
  SHA512:
6
- metadata.gz: 6d128baa0d6b1605117c0f9fa5ead20d8b306b28672e5efb10fc7a6df6a672c47d1a7b449967960b373e7e417c673e25e83eed23af6e5147070ab3457aff350a
7
- data.tar.gz: 7e696369664825849d4908e8d90c20abb48541ecfcda1047d064f4e99238217de7bf9e0bcb0ef673717d455e0a20657ded8cac0f07516b14c888966215e02429
6
+ metadata.gz: 84cb6025b635f7d6c30c47d6aaa698d3fc90707228f924e1e41fd4eddef13166743e92abb1f557710605ebe7d9a8444f0e6af95949df3321d848481cc8499ab9
7
+ data.tar.gz: f8c2d366313f7854f7f90e8a3b6c4ffd45ea1c6fef9558c9a2c7fa826a033a831e8e118b3754fca77c343613d8a285c17a810d662e3160590ff1347a92a106af
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  pkg
2
2
  Gemfile.lock
3
+ tmp
data/.travis.yml CHANGED
@@ -1,5 +1,8 @@
1
+ sudo: false
1
2
  language: ruby
3
+ cache: bundler
2
4
  rvm:
3
- - 2.2.0
4
- - 2.1.0
5
+ - 2.3.0
6
+ - 2.2.4
7
+ - 2.1.7
5
8
  - 2.0.0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Slackistrano Change Log
2
2
 
3
+ 1.1.0
4
+ -----
5
+
6
+ - Honor Capistrano's `--dry-run` [#33]
7
+ - Better error reporting if Slack API returns failure [#40]
8
+ - Allow posting to multiple channels by setting `:slack_channel` to an array [#37]
9
+
3
10
 
4
11
  1.0.0
5
12
  -----
data/README.md CHANGED
@@ -58,6 +58,13 @@ set :slack_token, "xxxxxxxxxxxxxxxxxxxxxxxx"
58
58
  set :slack_channel, '#general'
59
59
  ```
60
60
 
61
+ You can set `:slack_channel` (or any of the `:slack_channel_xxxx` settings) to an array and Slackistrano
62
+ will post to each channel. For example:
63
+
64
+ ```ruby
65
+ set :slack_channel, ['#general', '#ops']
66
+ ```
67
+
61
68
  Optionally, override the other slack settings.
62
69
 
63
70
  ```ruby
@@ -128,11 +135,10 @@ $ cap production slack:deploy:failed
128
135
  Slack allows you to send complex content, composed by fields. You can use the `fields` and `fallback` variables in order to have a well formatted message as follows:
129
136
 
130
137
  ```ruby
131
- set :slack_revision, `git rev-parse origin/master`.strip!
132
- set :slack_title_finished, nil
133
- set :slack_msg_finished, nil
134
- set :slack_fallback_finished, "#{fetch(:slack_deploy_user)} deployed #{fetch(:application)} on #{fetch(:stage)}"
135
- set :slack_fields_finished, [
138
+ set :slack_revision, `git rev-parse origin/#{fetch(:branch)}`.strip!
139
+ set :slack_msg_updated, nil
140
+ set :slack_fallback_updated, "#{fetch(:slack_deploy_user)} deployed #{fetch(:application)} on #{fetch(:stage)}"
141
+ set :slack_fields_updated, [
136
142
  {
137
143
  "title": "Project",
138
144
  "value": "<https://github.com/XXXXX/#{fetch(:application)}|#{fetch(:application)}>",
@@ -1,5 +1,6 @@
1
1
  namespace :slack do
2
2
  namespace :deploy do
3
+
3
4
  def make_attachments(stage, options={})
4
5
  attachments = options.merge({
5
6
  title: fetch(:"slack_title_#{stage}"),
@@ -12,23 +13,84 @@ namespace :slack do
12
13
  [attachments]
13
14
  end
14
15
 
16
+ def make_payload(stage)
17
+ payload = {
18
+ username: fetch(:slack_username),
19
+ icon_url: fetch(:slack_icon_url),
20
+ icon_emoji: fetch(:slack_icon_emoji),
21
+ }
22
+
23
+
24
+ payload[:attachments] = case stage
25
+ when :updated
26
+ make_attachments(stage, color: 'good')
27
+ when :reverted
28
+ make_attachments(stage, color: '#4CBDEC')
29
+ when :failed
30
+ make_attachments(stage, color: 'danger')
31
+ else
32
+ make_attachments(stage)
33
+ end
34
+
35
+ payload
36
+ end
37
+
38
+ def post_message(stage)
39
+ team = fetch(:slack_team)
40
+ token = fetch(:slack_token)
41
+ webhook = fetch(:slack_webhook)
42
+ via_slackbot = fetch(:slack_via_slackbot)
43
+ payload = make_payload(stage)
44
+
45
+ channels = fetch(:slack_channel)
46
+ stage_channel = "slack_channel_#{stage.to_s}".to_sym
47
+ if fetch(stage_channel)
48
+ channels = fetch(stage_channel)
49
+ end
50
+ channels = Array(channels)
51
+ if via_slackbot == false && channels.empty?
52
+ channels = [nil] # default webhook channel
53
+ end
54
+
55
+ channels.each do |channel|
56
+ payload[:channel] = channel
57
+
58
+ # This is a nasty hack, but until Capistrano provides an official way to determine if
59
+ # --dry-run was passed this is the only option.
60
+ # See https://github.com/capistrano/capistrano/issues/1462
61
+ if Capistrano::Configuration.env.send(:config)[:sshkit_backend] == SSHKit::Backend::Printer
62
+ info("[slackistrano] Slackistrano Dry Run:")
63
+ info("[slackistrano] Team: #{team}")
64
+ info("[slackistrano] Webhook: #{webhook}")
65
+ info("[slackistrano] Via Slackbot: #{via_slackbot}")
66
+ info("[slackistrano] Payload: #{payload.to_json}")
67
+
68
+ # Post to the channel.
69
+ else
70
+ http_response = Slackistrano.post(team: team,
71
+ token: token,
72
+ webhook: webhook,
73
+ via_slackbot: via_slackbot,
74
+ payload: payload)
75
+ if http_response.code !~ /^2/
76
+ error("[slackistrano] Slack API Failure!")
77
+ error("[slackistrano] URI: #{http_response.uri}")
78
+ error("[slackistrano] Code: #{http_response.code}")
79
+ error("[slackistrano] Message: #{http_response.message}")
80
+ error("[slackistrano] Body: #{http_response.body}") if http_response.message != http_response.body
81
+ end
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+ ######################################################################
88
+
15
89
  task :updating do
16
90
  set(:slack_deploy_or_rollback, 'deploy')
17
91
  if fetch(:slack_run_updating)
18
92
  run_locally do
19
- Slackistrano.post(
20
- team: fetch(:slack_team),
21
- token: fetch(:slack_token),
22
- webhook: fetch(:slack_webhook),
23
- via_slackbot: fetch(:slack_via_slackbot),
24
- payload: {
25
- channel: fetch(:slack_channel_updating) || fetch(:slack_channel),
26
- username: fetch(:slack_username),
27
- icon_url: fetch(:slack_icon_url),
28
- icon_emoji: fetch(:slack_icon_emoji),
29
- attachments: make_attachments(:updating)
30
- }
31
- )
93
+ post_message(:updating)
32
94
  end
33
95
  end
34
96
  end
@@ -37,40 +99,15 @@ namespace :slack do
37
99
  set(:slack_deploy_or_rollback, 'rollback')
38
100
  if fetch(:slack_run_reverting)
39
101
  run_locally do
40
- Slackistrano.post(
41
- team: fetch(:slack_team),
42
- token: fetch(:slack_token),
43
- webhook: fetch(:slack_webhook),
44
- via_slackbot: fetch(:slack_via_slackbot),
45
- payload: {
46
- channel: fetch(:slack_channel_reverting) || fetch(:slack_channel),
47
- username: fetch(:slack_username),
48
- icon_url: fetch(:slack_icon_url),
49
- icon_emoji: fetch(:slack_icon_emoji),
50
- attachments: make_attachments(:reverting)
51
- }
52
- )
102
+ post_message(:reverting)
53
103
  end
54
104
  end
55
105
  end
56
106
 
57
-
58
107
  task :updated do
59
108
  if fetch(:slack_run_updated)
60
109
  run_locally do
61
- Slackistrano.post(
62
- team: fetch(:slack_team),
63
- token: fetch(:slack_token),
64
- webhook: fetch(:slack_webhook),
65
- via_slackbot: fetch(:slack_via_slackbot),
66
- payload: {
67
- channel: fetch(:slack_channel_updated) || fetch(:slack_channel),
68
- username: fetch(:slack_username),
69
- icon_url: fetch(:slack_icon_url),
70
- icon_emoji: fetch(:slack_icon_emoji),
71
- attachments: make_attachments(:updated, color: 'good')
72
- }
73
- )
110
+ post_message(:updated)
74
111
  end
75
112
  end
76
113
  end
@@ -78,19 +115,7 @@ namespace :slack do
78
115
  task :reverted do
79
116
  if fetch(:slack_run_reverted)
80
117
  run_locally do
81
- Slackistrano.post(
82
- team: fetch(:slack_team),
83
- token: fetch(:slack_token),
84
- webhook: fetch(:slack_webhook),
85
- via_slackbot: fetch(:slack_via_slackbot),
86
- payload: {
87
- channel: fetch(:slack_channel_reverted) || fetch(:slack_channel),
88
- username: fetch(:slack_username),
89
- icon_url: fetch(:slack_icon_url),
90
- icon_emoji: fetch(:slack_icon_emoji),
91
- attachments: make_attachments(:reverted, color: '#4CBDEC')
92
- }
93
- )
118
+ post_message(:reverted)
94
119
  end
95
120
  end
96
121
  end
@@ -98,19 +123,7 @@ namespace :slack do
98
123
  task :failed do
99
124
  if fetch(:slack_run_failed)
100
125
  run_locally do
101
- Slackistrano.post(
102
- team: fetch(:slack_team),
103
- token: fetch(:slack_token),
104
- webhook: fetch(:slack_webhook),
105
- via_slackbot: fetch(:slack_via_slackbot),
106
- payload: {
107
- channel: fetch(:slack_channel_failed) || fetch(:slack_channel),
108
- username: fetch(:slack_username),
109
- icon_url: fetch(:slack_icon_url),
110
- icon_emoji: fetch(:slack_icon_emoji),
111
- attachments: make_attachments(:failed, color: 'danger')
112
- }
113
- )
126
+ post_message(:failed)
114
127
  end
115
128
  end
116
129
  end
@@ -1,3 +1,3 @@
1
1
  module Slackistrano
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
data/lib/slackistrano.rb CHANGED
@@ -16,8 +16,8 @@ module Slackistrano
16
16
  post_as_webhook(team: team, token: token, webhook: webhook, payload: payload)
17
17
  end
18
18
  rescue => e
19
- puts "There was an error notifying Slack."
20
- puts e.inspect
19
+ error("[slackistrano] Error notifying Slack!")
20
+ error("[slackistrano] Error: #{e.inspect}")
21
21
  end
22
22
 
23
23
  #
@@ -29,7 +29,7 @@ module Slackistrano
29
29
  text = payload[:attachments].collect { |a| a[:text] }.join("\n")
30
30
 
31
31
  Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
32
- http.request_post uri.request_uri, text
32
+ http.request_post uri, text
33
33
  end
34
34
  end
35
35
 
@@ -48,6 +48,4 @@ module Slackistrano
48
48
  Net::HTTP.post_form(uri, params)
49
49
  end
50
50
 
51
-
52
51
  end
53
-
data/slackistrano.gemspec CHANGED
@@ -24,4 +24,5 @@ Gem::Specification.new do |gem|
24
24
  gem.add_dependency 'json'
25
25
  gem.add_development_dependency 'rake'
26
26
  gem.add_development_dependency 'rspec'
27
+ gem.add_development_dependency 'pry'
27
28
  end
data/spec/tasks_spec.rb CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Slackistrano do
4
4
  before(:each) do
5
- Rake::Task['load:defaults'].invoke
5
+ Rake::Task['load:defaults'].execute
6
6
  end
7
7
 
8
8
  describe "before/after hooks" do
@@ -35,17 +35,40 @@ describe Slackistrano do
35
35
  %w[updating reverting updated reverted failed].each do |stage|
36
36
  it "posts to slack on slack:deploy:#{stage}" do
37
37
  set "slack_run_#{stage}".to_sym, ->{ true }
38
- expect(Slackistrano).to receive :post
38
+ expect(Slackistrano).to receive(:post).and_return(double(code: '200'))
39
39
  Rake::Task["slack:deploy:#{stage}"].execute
40
40
  end
41
41
 
42
42
  it "does not post to slack on slack:deploy:#{stage} when disabled" do
43
43
  set "slack_run_#{stage}".to_sym, ->{ false }
44
- expect(Slackistrano).not_to receive :post
44
+ expect(Slackistrano).not_to receive(:post)
45
45
  Rake::Task["slack:deploy:#{stage}"].execute
46
46
  end
47
47
  end
48
48
 
49
+ context "when :slack_channel is an array" do
50
+ %w[updating reverting updated reverted failed].each do |stage|
51
+ it "posts to slack on slack:deploy:#{stage} in every channel" do
52
+ set "slack_channel".to_sym, ->{ %w[one two] }
53
+ set "slack_run_#{stage}".to_sym, ->{ true }
54
+ expect(Slackistrano).to receive(:post).twice.and_return(double(code: '200'))
55
+ Rake::Task["slack:deploy:#{stage}"].execute
56
+ end
57
+ end
58
+ end
59
+
60
+ context "when --dry-run is passed" do
61
+ %w[updating reverting updated reverted failed].each do |stage|
62
+ it "does not post to slack on slack:deploy:#{stage}" do
63
+ set "slack_run_#{stage}".to_sym, ->{ true }
64
+ expect(Capistrano::Configuration.env.send(:config)).to receive(:[]).with(:sshkit_backend).and_return(SSHKit::Backend::Printer)
65
+ expect(Slackistrano).not_to receive(:post)
66
+ Rake::Task["slack:deploy:#{stage}"].execute
67
+ end
68
+ end
69
+ end
70
+
71
+
49
72
  [ # stage, color, channel
50
73
  ['updating', nil, nil],
51
74
  ['reverting', nil, nil],
@@ -91,7 +114,7 @@ describe Slackistrano do
91
114
  icon_emoji: ':emoji:',
92
115
  attachments: [attachment]
93
116
  }
94
- )
117
+ ).and_return(double(code: '200'))
95
118
  Rake::Task["slack:deploy:#{stage}"].execute
96
119
  end
97
120
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slackistrano
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Hallstrom
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-03 00:00:00.000000000 Z
11
+ date: 2016-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capistrano
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description: Send notifications to Slack about Capistrano deployments.
70
84
  email:
71
85
  - philip@pjkh.com
@@ -108,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
122
  version: '0'
109
123
  requirements: []
110
124
  rubyforge_project:
111
- rubygems_version: 2.4.3
125
+ rubygems_version: 2.4.6
112
126
  signing_key:
113
127
  specification_version: 4
114
128
  summary: Send notifications to Slack about Capistrano deployments.