lita-capistrano 0.1.3 → 0.2.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: c3c19a8b4e1c2c29eeea20d0900ec200abecc545
4
- data.tar.gz: d4d457dbf0e1162edf8d94adaead7fedf93edebd
3
+ metadata.gz: c1f3c26d550035dc25ff4a29fde961965b2aa3b3
4
+ data.tar.gz: 2e90474c1194516456af12e226b0179d441843d7
5
5
  SHA512:
6
- metadata.gz: 570635dd217d78445f09ea31570dcaf5ec6cf3feaaf02961e70c128e3a233288c0cffe9939d1f3e97cc1f0cc449d347cd679a399ac470bdd3b672a370e437267
7
- data.tar.gz: e9c00cfafe4d5020c3b29149200ad7e98e7360b910427af8e428103f45b87c0799f5c60b2404234587082aca3651682e5fdff1d9c38465911731eefa42dba120
6
+ metadata.gz: 9389b67972da5324053a44b9e332a9d456064429f583570fa6c5057ceb7ea74ff5467cb1ae4a1d31621af950d94bcd34642782286aa4ea07d7945a28558326a9
7
+ data.tar.gz: cd4aa4c7a3f9852e4d26aa142c2120e5d1115bfd93f0f816340a6889e87e73a3c550fdb6c1974eb706317d498c3a490e050cfd530894da36099dd13cf58c2d86
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # lita-capistrano
2
2
 
3
- TODO: Add a description of the plugin.
3
+ [![Gem Version](https://badge.fury.io/rb/lita-capistrano.png)](http://badge.fury.io/rb/lita-capistrano)
4
+
5
+ **lita-capistrano** is a hanlder for [Lita](https://www.lita.io/) that allows you to use make deploys through your robot.
6
+
7
+ ## Requirements
8
+
9
+ In order to **lita-capistrano** to identify a good deploy from a failed one, you capistrano script should always end with a message.
4
10
 
5
11
  ## Installation
6
12
 
@@ -12,8 +18,91 @@ gem "lita-capistrano"
12
18
 
13
19
  ## Configuration
14
20
 
15
- TODO: Describe any configuration attributes the plugin exposes.
21
+ ### Required attributes
22
+
23
+ * `server` (String) – The deploy server host.
24
+
25
+ * `server_user` (String) – The deploy server host ssh user.
26
+
27
+ * `server_password` (String) – The deploy server host ssh password.
28
+
29
+ * `deploy_tree` (String) – A json configuration of how deploys work.
30
+
31
+ ### Example
32
+
33
+ ``` ruby
34
+ Lita.configure do |config|
35
+ config.handlers.capistrano.server = "capistrano-deploy.com"
36
+ config.handlers.capistrano.server_user = "lita"
37
+ config.handlers.capistrano.server_password = "secret"
38
+ end
39
+
40
+ config.handlers.capistrano.deploy_tree = {
41
+ first_app: {
42
+ qa: {
43
+ dir: "/capistrano/first_app/qa",
44
+ auth_group: "first_app_qa", # auth_group required to be able to deploy
45
+ channel: "first_app_channel", # not required, if configured limits deploys to this channel
46
+ envs: [
47
+ "qa1",
48
+ "qa2"
49
+ ]
50
+ },
51
+ staging: {
52
+ dir: "/capistrano/fist_app/staging",
53
+ auth_group: "first_app_staging",
54
+ envs: [
55
+ "stagin1",
56
+ "staging2",
57
+ "staging3"
58
+ ]
59
+ }
60
+ },
61
+ second_app: {
62
+ prod: {
63
+ dir: "/capistrano/second_app/production",
64
+ auth_group: "second_app_staging",
65
+ channel: "second_app_prod_channel",
66
+ envs: [
67
+ "dc1",
68
+ "dc2"
69
+ ]
70
+ }
71
+ }
72
+ ```
16
73
 
17
74
  ## Usage
18
75
 
19
- TODO: Describe the plugin's features and how to use them.
76
+ List available apps for deploy:
77
+
78
+ ```
79
+ Lita: deploy list
80
+ ```
81
+
82
+ List available app areas for deploy:
83
+
84
+ ```
85
+ Lita: deploy list [APP]
86
+ ```
87
+
88
+ List required auth groups to deploy:
89
+
90
+ ```
91
+ Lita: deploy auth list [APP]
92
+ ```
93
+
94
+ Deploy a tag or branch:
95
+
96
+ ```
97
+ Lita: deploy [APP] [AREA] [ENV] [TAG]
98
+ ```
99
+
100
+ Rollback last tag or branch:
101
+
102
+ ```
103
+ Lita: deploy [APP] [AREA] [ENV] rollback
104
+ ```
105
+
106
+ ## License
107
+
108
+ [MIT](http://opensource.org/licenses/MIT)
@@ -46,6 +46,14 @@ module Lita
46
46
  area = response.matches[0][1]
47
47
  env = response.matches[0][2]
48
48
  tag = response.matches[0][3]
49
+ allowed_channel = config.deploy_tree[app.to_sym][area.to_sym][:channel]
50
+ room_id = response.message.source.room_object.id
51
+
52
+ # Do not deploy if not in the right channel, only if channel is
53
+ # set in config.
54
+ if !allowed_channel.nil? && !allowed_room?(room_id, allowed_channel)
55
+ return response.reply("Deploy da app #{app} #{area} permitido somente no canal ##{allowed_channel}")
56
+ end
49
57
 
50
58
  unless area_exists?(area)
51
59
  return response.reply("A área informada é inválida.")
@@ -54,11 +62,11 @@ module Lita
54
62
  return response.reply("O ambiente informado é inválido.")
55
63
  end
56
64
 
57
- # Pre deploy check
65
+ # Pre deploy check, if no deploy in progress, deploy-tracker will
66
+ # trigger :deploy_checked to continue the deploy.
58
67
  deploy_in_progress?(app, area, env, tag, response)
59
68
  end
60
69
 
61
-
62
70
  def area_exists?(area)
63
71
  config.deploy_tree[:commerce].include?(area.to_sym)
64
72
  end
@@ -109,58 +117,104 @@ module Lita
109
117
  tag = payload[:tag]
110
118
  response = payload[:response]
111
119
  dir = config.deploy_tree[app.to_sym][area.to_sym][:dir]
120
+ responsible_user = response.user.mention_name
121
+ target = response.message.source.room_object
122
+
123
+ # Default initial message
124
+ initial_message = "#{responsible_user}: Deploy da tag #{tag} iniciado no ambiente #{env}."
112
125
 
113
- # Deploy start
114
- response.reply("#{response.user.mention_name}: Deploy da tag #{tag} iniciado no ambiente #{env}.")
126
+ if (tag == "rollback")
127
+ # Change the initial message in case of rollback
128
+ initial_message = "#{responsible_user}: Rollback iniciado no ambiente #{env}."
129
+ end
130
+
131
+ # Deploy/Rollback start
132
+ response.reply(initial_message)
115
133
  start_time = Time.now
116
134
  robot.trigger(:deploy_started,
117
135
  app: app,
118
136
  area: area,
119
137
  env: env,
120
138
  tag: tag,
121
- responsible: response.user.mention_name,
139
+ responsible: responsible_user,
122
140
  start_time: start_time)
123
141
 
124
- # Deploy execution
125
- output = deploy(dir, env, tag)
142
+ # Deploy/Rollback execution
143
+ output = ""
144
+ if (tag == "rollback")
145
+ output = rollback(dir, env)
146
+ else
147
+ output = deploy(dir, env, tag)
148
+ end
149
+
126
150
  # After deploy stopped
127
151
  finish_time =Time.now
128
152
 
129
- # The deploy:restart could be in two positions depending on the
130
- # capistrano config
131
- if (output.lines.last.include? "deploy:restart") || (output.lines.last(5)[0].include? "deploy:restart")
153
+ msg_components = {}
154
+
155
+ # Send back a message indicating the deploy status
156
+ if !output[:error]
132
157
  robot.trigger(:deploy_finished,
133
158
  app: app,
134
159
  area: area,
135
160
  env: env,
136
161
  tag: tag,
137
- responsible: response.user.mention_name,
162
+ responsible: responsible_user,
138
163
  start_time: start_time,
139
164
  finish_time: finish_time,
140
165
  status: 'success')
141
- return response.reply("#{response.user.mention_name}: Deploy da tag #{tag} no ambiente #{env} realizado com sucesso!")
142
- elsif output.lines.last.include? "status code 32768"
166
+ msg_components = {title: "Finalizado com sucesso!",
167
+ color: "good",
168
+ text: ""}
169
+ elsif output[:data].lines.last.include? "status code 32768"
143
170
  robot.trigger(:deploy_finished,
144
171
  app: app,
145
172
  area: area,
146
173
  env: env,
147
174
  tag: tag,
148
- responsible: response.user.mention_name,
175
+ responsible: responsible_user,
149
176
  start_time: start_time,
150
177
  finish_time: finish_time,
151
178
  status: 'invalid tag')
152
- return response.reply("#{response.user.mention_name}: A tag #{tag} informada não existe. Deploy não realizado.")
179
+ msg_components = {title: "A tag informada não existe.",
180
+ color: "warning",
181
+ text: ""}
153
182
  else
154
183
  robot.trigger(:deploy_finished,
155
184
  app: app,
156
185
  area: area,
157
186
  env: env,
158
187
  tag: tag,
159
- responsible: response.user.mention_name,
188
+ responsible: responsible_user,
160
189
  start_time: start_time,
161
190
  finish_time: finish_time,
162
191
  status: 'error')
163
- return response.reply("#{response.user.mention_name}: Ocorreu um erro na execução do deploy da tag #{tag} no ambiente #{env}.")
192
+ msg_components = {title: "Error!",
193
+ color: "danger",
194
+ text: output[:data]}
195
+ end
196
+
197
+ # generate the Attachment for slack
198
+ attachment = gen_deploy_msg(msg_components[:title],
199
+ msg_components[:color],
200
+ msg_components[:text],
201
+ responsible_user,
202
+ app,
203
+ area,
204
+ env,
205
+ tag)
206
+
207
+ # Default message for other adapters
208
+ message = "Deploy - #{msg_components[:title]}. #{msg_components[:text]}"
209
+ if (tag == "rollback")
210
+ message = "Rollback - #{msg_components[:title]}. #{msg_components[:text]}"
211
+ end
212
+
213
+ case robot.config.robot.adapter
214
+ when :slack
215
+ return robot.chat_service.send_attachments(target, attachment)
216
+ else
217
+ robot.send_message(target, message)
164
218
  end
165
219
  end
166
220
 
@@ -177,7 +231,7 @@ module Lita
177
231
  %r{^deploy\s+auth\s+list},
178
232
  :deploy_auth_list,
179
233
  command: false,
180
- help: { "deploy auth list [APP] " => "List available apps for deploy"}
234
+ help: { "deploy auth list [APP] " => "List required auth groups to deploy"}
181
235
  )
182
236
  end
183
237
 
@@ -191,6 +245,7 @@ module Lita
191
245
  restrict_to: [:admins, value[:auth_group].to_sym],
192
246
  help: { "deploy #{app} #{area} ENV TAG " => "Executa deploy da app #{app} na area #{area}"}
193
247
  )
248
+
194
249
  end
195
250
  end
196
251
  end
@@ -199,13 +254,69 @@ module Lita
199
254
  output = ssh_exec("cd #{dir}; cap #{env} deploy tag=#{tag}")
200
255
  end
201
256
 
257
+ def rollback(dir, env)
258
+ output = ssh_exec("cd #{dir}; cap #{env} deploy:rollback")
259
+ end
260
+
202
261
  def ssh_exec(cmd)
203
- #TODO tornar acesso ao servidor dinamico entro prod e test
204
- Net::SSH.start(config.server, config.server_user, :password => config.server_password) do |ssh|
205
- @output = ssh.exec!(cmd)
262
+ Net::SSH.start(config.server, config.server_user, password: config.server_password) do |ssh|
263
+ exec_ssh(ssh, cmd)
264
+ end
265
+ end
266
+
267
+ def exec_ssh(ssh, cmd)
268
+ ssh.exec! cmd do |ch, stream, data|
269
+ @output = get_deploy_output(stream, data)
206
270
  end
207
271
  @output
208
272
  end
273
+
274
+ def get_deploy_output(stream, data)
275
+ if stream == :stderr
276
+ { data: "#{data}", error: true }
277
+ else
278
+ { data: "#{data}", error: false }
279
+ end
280
+ end
281
+
282
+
283
+ def gen_deploy_msg (title, color, body, user, app, area, env, tag)
284
+ msg = Adapters::Slack::Attachment.new(
285
+ body,
286
+ title: "Deploy - #{title}",
287
+ color: "#{color}",
288
+ pretext: "@#{user}:",
289
+ fields: [
290
+ {
291
+ title: "App",
292
+ value: app,
293
+ short: true
294
+ },
295
+ {
296
+ title: "Área",
297
+ value: area,
298
+ short: true
299
+ },
300
+ {
301
+ title: "Ambiente",
302
+ value: env,
303
+ short: true
304
+ },
305
+ {
306
+ title: "tag",
307
+ value: tag,
308
+ short: true
309
+ },
310
+ ]
311
+ )
312
+ end
313
+
314
+ def allowed_room?(room_id, allowed_channel)
315
+ room = Lita::Room.find_by_id(room_id)
316
+ return false if room.nil?
317
+ return true if room.metadata["name"] == allowed_channel
318
+ end
319
+
209
320
  end
210
321
 
211
322
  Lita.register_handler(Capistrano)
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "lita-capistrano"
3
- spec.version = "0.1.3"
3
+ spec.version = "0.2.0"
4
4
  spec.authors = ["Alexandre Gomes"]
5
5
  spec.email = ["alejdg@outlook.com.br"]
6
6
  spec.summary = "A Lita handler to integrate with Capistrano.rb"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-capistrano
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Gomes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-25 00:00:00.000000000 Z
11
+ date: 2016-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lita