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 +4 -4
- data/README.md +92 -3
- data/lib/lita/handlers/capistrano.rb +132 -21
- data/lita-capistrano.gemspec +1 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c1f3c26d550035dc25ff4a29fde961965b2aa3b3
         | 
| 4 | 
            +
              data.tar.gz: 2e90474c1194516456af12e226b0179d441843d7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 9389b67972da5324053a44b9e332a9d456064429f583570fa6c5057ceb7ea74ff5467cb1ae4a1d31621af950d94bcd34642782286aa4ea07d7945a28558326a9
         | 
| 7 | 
            +
              data.tar.gz: cd4aa4c7a3f9852e4d26aa142c2120e5d1115bfd93f0f816340a6889e87e73a3c550fdb6c1974eb706317d498c3a490e050cfd530894da36099dd13cf58c2d86
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,12 @@ | |
| 1 1 | 
             
            # lita-capistrano
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            [](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 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
            -
                     | 
| 114 | 
            -
             | 
| 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:  | 
| 139 | 
            +
                                  responsible: responsible_user,
         | 
| 122 140 | 
             
                                  start_time: start_time)
         | 
| 123 141 |  | 
| 124 | 
            -
                    # Deploy execution
         | 
| 125 | 
            -
                    output =  | 
| 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 | 
            -
                     | 
| 130 | 
            -
             | 
| 131 | 
            -
                     | 
| 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:  | 
| 162 | 
            +
                                    responsible: responsible_user,
         | 
| 138 163 | 
             
                                    start_time: start_time,
         | 
| 139 164 | 
             
                                    finish_time: finish_time,
         | 
| 140 165 | 
             
                                    status: 'success')
         | 
| 141 | 
            -
                     | 
| 142 | 
            -
             | 
| 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:  | 
| 175 | 
            +
                                    responsible: responsible_user,
         | 
| 149 176 | 
             
                                    start_time: start_time,
         | 
| 150 177 | 
             
                                    finish_time: finish_time,
         | 
| 151 178 | 
             
                                    status: 'invalid tag')
         | 
| 152 | 
            -
                       | 
| 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:  | 
| 188 | 
            +
                                    responsible: responsible_user,
         | 
| 160 189 | 
             
                                    start_time: start_time,
         | 
| 161 190 | 
             
                                    finish_time: finish_time,
         | 
| 162 191 | 
             
                                    status: 'error')
         | 
| 163 | 
            -
                       | 
| 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  | 
| 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 | 
            -
                     | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 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)
         | 
    
        data/lita-capistrano.gemspec
    CHANGED
    
    
    
        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. | 
| 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- | 
| 11 | 
            +
            date: 2016-02-04 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: lita
         |