Skip to content

Commit 540676d

Browse files
author
Ben Lavender
committed
add some why
1 parent b88c9e8 commit 540676d

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

docs/why.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Why Chatops RPC?
2+
3+
Chatops RPC is distilled from several years' experience working with Chatops
4+
at GitHub. The protocol is simple and will not cover every use case, but
5+
internal adoption has been excellent.
6+
7+
### What came first
8+
9+
#### Hubot
10+
11+
Our first generation of chatops were written directly as Hubot scripts. These
12+
work fine for situations where there's an existing API that's well-supported.
13+
But if the API wasn't designed to do what the chat command wanted, a single
14+
command might end up making several REST API calls, with all the associated
15+
error handling, responses, etc. REST API endpoints created explicitly for chat
16+
commands tended to be challenging to test end-to-end, since lots of the
17+
logic would end up wrapped in hubot and outputting chat-adapter-specific things.
18+
19+
#### Shell
20+
21+
Next we wrote a bridge from a pile of shell scripts to hubot. This had great
22+
adoption, but it had its own problems. Security contexts were often mixed up
23+
with each other, so there were very poor boundaries between what access tokens
24+
a script needed and had available. Several different services made more
25+
sense being written as shell, ruby, python, go, and more, and this mishmash
26+
meant that in practice very little code was reused or tested.
27+
28+
#### The pattern
29+
30+
Over time, we settled on a new pattern: direct hubot bindings to API endpoints
31+
written just for hubot. This resulted in a few services with a few hundred
32+
lines of boilerplate node, wrapping API calls.
33+
34+
This pattern was a winner, though. Servers were able to test their commands
35+
end-to-end, missing out only on the regular expressions that might trigger a
36+
command. Responses and changes to state could be tested in one place.
37+
38+
Chatops RPC is a distillation and protocol around the last pattern of RPC
39+
endpoints with a one-to-one mapping to a chat command.
40+
41+
### Authentication
42+
43+
Chatops RPC servers need to trust the username that the chat bridge gives them.
44+
This means that a shared token gives servers the ability to misrepresent users
45+
with other servers. In this case, there's a lot of trust built in to the chat
46+
bridge, and we find this maps well to the asymmetric crypto authentication.
47+
48+
### Keyword Arguments
49+
50+
We pair this system with <https://github.com/github/hubot-chatops-rpc>, which
51+
provides generic argument support for long arguments, like `--argument foo`.
52+
While regexes create much more natural commands, rarely used options tend to
53+
create ugly regexes that are hard to test. If a command can potentially take 10
54+
arguments, it's almost certain the regex will have unhandled edge cases. Generic
55+
arguments provide an easy way to take rarely-used options. These are not part
56+
of the Chatops RPC protocol but it's highly recommended to use a client that
57+
supports them.
58+
59+
Keyword arguments are also important for searching chat history. In the past, we
60+
had several commands that had strange regex forms for different operations. It's
61+
hard to find examples to use these unusual forms. For example, `.deploy!` has
62+
become `.deploy --force`, which is much clearer for new employees and easier to
63+
find examples of.
64+
65+
### Testing
66+
67+
Highly testable patterns were a core consideration of Chatops RPC. GitHub had
68+
grown quite dependent on Chatops as a core part of its workflow, but a very
69+
large number of them were not tested. We've had several instances of important
70+
but rarely-used chat operations failing during availability incidents. Chatops
71+
RPC brings the entire flow to the server, and this results in highly testable
72+
operations that will work when they need to.
73+
74+
### Prefixes
75+
76+
Prefixes provide a way for more than one of the same endpoint to coexist. Over
77+
the years, we've had several systems with staging environments or other
78+
contexts. Ad-hoc solutions, unique to each, were created, forcing developers to
79+
learn new ways to manage the context of multiple chat-connected systems.
80+
81+
Prefixes provide a way to have two systems, such as `.deploy` and
82+
`.deploy-staging` for a staging deployments system. Prefixes also provide a way
83+
to interface with endpoints that are associated with a resource they manage. For
84+
example, if your site has multiple kubernetes clusters, perhaps a server to
85+
manage each would be stood up, one per cluster, each including the cluster
86+
name in the prefix. This allows you to write "manage kubernetes cluster" once
87+
but have `.kubectl@cluster1 list pods` and `.kubectl@cluster2 list pods`.
88+
89+
Internally, we use Hubot middleware to alias some very commonly used commands
90+
to shorter versions that do not use the same prefix.

0 commit comments

Comments
 (0)