Cogy
Cogy integrates Cog with Rails in a way that writing & deploying commands from your application is a breeze.
See the API documentation here.
Status
Cogy is still in public alpha.
While we use it in production, it's still under heavy development. This means that there are a few rough edges and some important bits are missing.
However we'd love any feedback, suggestions or ideas.
Why
Creating a ChatOps command that talks with a Rails app typically involves writing a route, maybe a controller, an action and code to handle the command arguments and options.
This is a tedious and repetitive task and involves a lot of boilerplate code each time someone wants to add a new command.
Cogy is an opinionated library that provides a way to get rid of all the repetitive work.
Writing a new command and deploying it is as simple as:
# in cogy/my_commands.rb
on "foo", desc: "Echo a foo bar back at you!" do
"@#{handle}: foo bar"
end
...and deploying! After a second or so, the command is ready to be used.
How it works
Cogy is essentially three things:
- An opinionated way to write, manage & ship commands: All Cogy commands are
defined in your Rails app and end up invoking a single executable within the
Relay. Cogy also provides bundle versioning and dynamically generates the
installable bundle config, which is also served by your Rails application
and consumed by the
cogy:installcommand that installs the new Cogy-generated bundle when you deploy your application. - A library that provides the API for defining the commands. This library
is integrated in your application via a Rails Engine that routes the incoming
requests to their respective handlers. It also creates the
/inventoryendpoint, which serves the installable bundle configuration in YAML and can be consumed directly by thecogy:installcommand. - A Cog bundle that contains the
executable
that all the commands end up invoking.
It is placed inside the Relays and performs the requests to your application
when a user invokes a command in the chat. It then posts the result back
to the user. It also contains the
cogy:installcommand for automating the task of installing the new bundle when a command is added/modified.
Take a look at the relevant diagrams for an illustration of how Cogy works.
Requirements
- cogy bundle
- Ruby 2.1+
- Tested with Rails 4.2
Install
Add it to your Gemfile:
gem "cogy"
Then run bundle install
Next, run the generator:
$ bin/rails g cogy:install
This will create a sample command, mount the engine and add a sample configuration initializer in your application.
Usage
Defining a new command:
# in cogy/commands.rb
on "foo", desc: "Echo a bar" do
"bar"
end
This will print "bar" back to the user who calls !foo in Slack, for example.
Inside the block there are the following pre-defined helpers available:
#args: an array containing the arguments passed to the command#opts: a hash containing the options passed to the command#handle: the chat handle of the user who called the command#env: a hash containing the Cogy environment, that is, every environment variable starting with 'COGY_' and set in the Relay
For instructions on defining your own helpers, see Helpers.
A more complete example:
# in cogy/commands.rb
on "calc",
args: [:a, :b],
opts: { op: { type: "string" } },
desc: "Performs a calculation between numbers <a> and <b>",
examples: "myapp:calc sum 1 2" do
op = opts[:op].to_sym
result = args.map(&:to_i).inject(&op)
"Hello @#{user}, the result is: #{result}"
end
For more examples see the test commands.
Configuration
The configuration options provided are the following:
# in config/initializers/cogy.rb
Cogy.configure do |config|
# Used in the generated bundle config YAML.
#
# Default: "cogy"
config.bundle_name = "myapp"
# Used in the generated bundle config YAML.
#
# Default: "Cogy-generated commands"
config.bundle_description = "myapp-generated commands from Cogy"
# Can be either a string or an object that responds to `#call` and returns
# a string.
config.bundle_version = "0.0.1"
# if you used a callable object, it will be evaluated each time the inventory
# is called. This can be useful if you want the version to change dynamically
# when it's needed.
#
# For example, this will change the version only when a command is
# added or is modified (uses the 'grit' gem).
config.bundle_version = -> {
repo = Grit::Repo.new(Rails.root.to_s)
repo.log("HEAD", "cogy/", max_count: 1).first.date.strftime("%y%m%d.%H%M%S")
}
# The path in the Relay where the cogy command executable is located at.
config.executable_path = "/cogcmd/cogy"
# Paths in your application where the files that define the commands live in.
# For example the default value will search for all `*.rb` files in the `cogy/`
# directory relative to the root of your application.
#
# Default: ["cogy"]
config.command_load_paths = "cogy"
end
You can use the generator to quickly create a config initializer in your app:
$ bin/rails g cogy:config
Helpers
It is possible to define helpers that can be used throughout commands. They can be defined during configuration and can accept a variable number of arguments, or no arguments at all.
Let's define a helper that fetches a Shops address of the user who called the
command:
Cogy.configure do |c|
c.helper(:shop_address) { Shop.find_by(owner: handle).address }
end
(Note that custom helpers also have access to the default helpers like
handle, args etc.)
Then we could have a command like this:
on "shop_address", desc: "Returns the user's Shop address" do
"@#{handle}: Your shop's address is #{shop_address}"
end
We can also define helpers that accept arguments:
Cogy.configure do |c|
c.helper(:format) { |answer| answer.titleize }
end
Then in our command we could call it like so:
on "foo", desc: "Nothing special" do
format "hello there, how are you today?"
end
Rails' URL helpers are also available inside the commands.
Error template
When a command throws an error the default error template is rendered, which is the following:
@<%= @user %>: Command '<%= @cmd %>' returned an error.
```
<%= @exception.class %>:<%= @exception.message %>
```
It can be overriden in the application by creating a view in
app/views/cogy/error.text.erb.
Authors
License
Cogy is licensed under MIT. See LICENSE.