⚡️Lightning Talk

by Carlos Contreras

Dinosaur.JS

Here's a small comercial.

production => happy-branch
staging4   => rc99.4.0
uct        => ui4
fixture    => upgrade-webpack
saintbox   => mistery-branch

Tired of keeping a track on what's deployed on all test environments?

Sick of searching trough all PR/MR to prepare release notes?

Can't memorize the meeting url?

Text

How many times have you found yourself doing repetitive things that can be easily automated in your daily basis?

* Translations is a different story

Build a Slack Integration with Rails 5.

TRIBUTE

BOT

🤖 Specs

secret-server

  • 512 MB Memory
  • 20 GB Disk
  • Ubuntu 16.04.2 x64

Meet the tribute bot!

 

Messages that begin with a slash (/) are commands and will behave differently from regular messages.


When a slash command is invoked, Slack sends your server a HTTP POST of data describing the user's invocation.

https://tribute-bot.com/slack/slash_commands/whats_in

🤖 Slash Commands

token=gIkuvaNzQIHg97ATvDxqgjtO
team_id=T0001
team_domain=example
enterprise_id=E0001
enterprise_name=Globular%20Construct%20Inc
channel_id=C2147483705
channel_name=test
user_id=U2147483697
user_name=Steve
command=/whats_in
text=saintbox
response_url=https://hooks.slack.com/commands/1234/5678

For example, imagine that there's an app command installed called /whats_in. If someone on the tribute-bot.slack.com team types /weather stainbox in the #test channel and hits enter, this data would be posted to the external URL:

🤖 What can it do?

🌟   /release_notes branch repo
          Gets RC release notes 📝

/release_notes ui4 gitlab
 

 /release_notes rc43 github
 

Examples

🤖 What can it do?

🌟   /whats_in environment
            Show me what's deployed! 🚀

/whats_in saintbox
 

Example

/whats_in fixture
 

🌟 /whats_running
          Tell me what's deployed in all environments? 👁

/whats_running

Example

🤖 What can it do?

🌟 Daily Reminders
          Did you forget you had that meeting today? 😱

Example

🤖 What can it do?

It's DEMO time! 🚀

How it works? 🤔

class Slack::SlashCommandsController < Slack::BaseCommandsController
  include Slack::CustomMessage

  def release_notes
    render status: 200, :json => message('Aye aye! please hold your seat, this can take a while 🕐')
    HardWorker.perform_async(release_notes_params.to_h)
  end

  def whats_running_where
    whats_running_where_command = DeployedBranch::BranchNames.call

    if whats_running_where_command.success?
      branches_data = whats_running_where_command.deployed_branches
      render status: 200, :json => message_attachments(deployed_branch_messages(branches_data))
    else
      render status: 200, :json => message(whats_running_where_command.error)
    end
  end

  def whats_in
    branch_name_command = DeployedBranch::BranchName.call(environment: params['text'])

    if branch_name_command.success?
      branch_data = branch_name_command.deployed_branch
      render status: 200, :json => message_attachments(deployed_branch_messages(branch_data))
    else
      render status: 200, :json => message(branch_name_command.error)
    end
  end

end

🤖 SlashCommandController

class DeployedBranch::BranchName
  include HTTParty
  include AyeCommander::Command

  requires :environment
  returns :deployed_branch, :error
  basic_auth Rails.application.secrets.basic_auth['username'], Rails.application.secrets.basic_auth['password']

  before do
    @url = generate_url
  end

  def call
    get_revision
    parse_revision
  end

  def get_revision
    response  = HTTParty.get(@url)
    @revision = response.body.strip!

  rescue SocketError => e
    Rails.logger.error(e.message)
    @error = "That enviroment doesn't exits, are you sure you typed it correctly? 🤔"
    fail!(:invalid_environment_name) && abort!
  end

  def parse_revision
    response = @revision.split(' ')

    @deployed_branch = {}.tap do |h|
      h[:environment] = environment.capitalize
      h[:branch]      = response[1]
      h[:version]     = response[3].strip[0..7]
      h[:timestamp]   = response[7].to_time.to_formatted_s(:long)
      h[:author]      = response[9]
    end
  end


  def generate_url
    base_url = Rails.application.secrets.base_uri
    if environment.to_sym == :production
      "https://#{base_url}/REVISION.txt"
    else
      "https://#{environment}.#{base_url}/REVISION.txt"
    end
  end

end

🤖 BranchName Command

class ReleaseNotes::GenericRepo
  include AyeCommander::Command

  requires :repository_name, :target_branch
  returns :release_notes, :error

  before do
    @adapter = initialize_git
  end

  def call
    prepare_branch
    get_release_notes
  end

  def initialize_git
    ReleaseNotes::RepoAdapter.get(repository_name)
  rescue => e
    Rails.logger.error e.message
    @error = "Beep Bop Boop, I couldn't find repository *#{repository_name}*, are you sure it exists? 👁"
    fail!(:invalid_repository_name) && abort!
  end

  def prepare_branch
    @adapter.prepare_branch(target_branch)
  rescue => e
    Rails.logger.error e.message
    @error = "Error fetching branch: #{target_branch}, are you sure it exists in remote? 😱"
    fail!(:invalid_branch_name) && abort!
  end

  def get_release_notes
    begin
      @release_notes = @adapter.release_notes(@branch)
    rescue => e
      Rails.logger.error e.message
      @error = "Erro: Something is burning 🔥🚒!"
      fail!(:something_went_wrong) && abort!
    end
  end
end

🤖 ReleaseNotes Command

class ReleaseNotes::GithubRepo

  def initialize
    @git = Git.open(Rails.application.secrets.github_repository)
  end

  def prepare_branch(branch)
    @git.checkout(:master)
    @git.pull

    @git.checkout(branch)
    @git.pull(:origin, branch)
  end

  def release_notes(branch)
      release_notes = []
      @git.log(MAX_LOG_NUM).between(:master, branch).each do |commit|
        commit_array = @git.object(commit).contents.split("\n").reject!(&:empty?)
        commit_array.each do |message|
          if message =~ /Merge pull request #/
            release_notes << "#{message.scan(/#\d+/).first} #{commit_array.last}"
          end
        end
      end
      release_notes
  end

end

🤖 GithubRepo

🤖 What's next?

✅ Conversational Responses

✅ Assign Pull requests (?)

🤖 What's next?

✅ Deploy to test environments (?)

🤖 What's next?

Brainstorm! 🤓

  • Select next tribute
  • View release notes from past releases
  • Place burrito orders

Random Ideas:

Thank you!

https://github.com/DarthCharles/tribute-bot

Made with Slides.com