slackistrano 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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.