UNPKG

15 kBMarkdownView Raw
1# @atomist/automation-client
2
3[![atomist sdm goals](http://badge.atomist.com/T29E48P34/atomist/automation-client-ts/bdaca35b-0cb1-4fbf-8596-a27777b46974)](https://app.atomist.com/workspace/T29E48P34) [![npm version](https://badge.fury.io/js/%40atomist%2Fautomation-client.svg)](https://badge.fury.io/js/%40atomist%2Fautomation-client)
4
5[Node][node] module [`@atomist/automation-client`][automation-client]
6for creating Atomist development automations. Development automations take the following forms:
7
8- Bot commands - create bot commands using _command handlers_
9- Respond to events - use _event handlers_ to automatically
10 take action when events, like someone commenting on an issue,
11 happen
12- Ingestors - define your own, custom events that you can then take
13 action on
14
15The automation-client provide the ability to run a client that
16connects to the Atomist API so it can receive and act on commands and
17events.
18
19See [atomist.com][atomist] and [docs.atomist.com][docs] for more
20detailed information.
21
22[node]: https://nodejs.org/ (Node.js)
23[automation-client]: https://www.npmjs.com/package/@atomist/automation-client
24[docs]: https://docs.atomist.com/ (Atomist Documentation)
25
26## Concepts
27
28Atomist is a service and API that enables development automation. The
29Atomist service builds and maintains a model of the things that matter
30to your development team. You can then use out of the box automations
31or build your own automations acting on this model.
32
33For more information, please read [Concepts](docs/Concepts.md).
34
35## Getting Started
36
37Please install [Node.js][node]. To verify that the right versions are
38installed, please run:
39
40```
41$ node -v
42v8.4.0
43$ npm -v
445.4.1
45```
46
47### Using the `automation-client` module from your project
48
49To start using this module in your Node.js application, you have to add a dependency to it to your `package.json`
50by running the following command:
51
52```
53$ npm install @atomist/automation-client --save
54```
55
56You can find reference documentation at https://atomist.github.io/automation-client-ts/ .
57
58### Starting from a Sample
59
60We also provide a working project with some basic automations that you can use to get started quickly. The repository
61is at [atomist/automation-seed-ts](https://github.com/atomist/automation-seed-ts).
62
63To get started run the following commands:
64
65```
66$ git clone git@github.com:atomist/automation-seed-ts.git
67$ cd automation-seed-ts
68$ npm install
69```
70
71See the [automation-seed-ts README][seed-readme] for further
72instructions.
73
74[seed-readme]: https://github.com/atomist/automation-seed-ts#readme
75
76## Implementing Automations
77
78### Command Handlers
79
80Commands are automations that can be invoked via a Chat bot, curl or web interface.
81
82To create a command take a look at the following example:
83
84```typescript
85import { CommandHandler, Parameter} from "@atomist/automation-client/decorators";
86import { HandleCommand, HandlerContext, HandlerResult } from "@atomist/automation-client/Handlers";
87
88@CommandHandler("Sends a hello back to the client", "hello world")
89// ^ -- defines the command to trigger
90// " this handler from the bot
91export class HelloWorld implements HandleCommand {
92// ^ -- a command handler implements the HandleCommand
93// interface
94
95 @Parameter({ pattern: /^.*$/, required: true })
96// ^ ^ ^ -- parameters can be marked required or optional
97// ^ ^ -- the parameter can be validated against a RegExp pattern
98// ^ -- this defines a user-provided parameter named 'name'
99 public name: string;
100
101
102 public handle(ctx: HandlerContext): Promise<HandlerResult> {
103// ^ ^ -- HandlerContext provides access to a 'MessageClient' for sending
104// ^ messages to the bot as well as a 'GraphClient' to query your
105// ^ data using GraphQL
106// ^ -- this method is the body of the handler and where the actual code goes
107 return ctx.messageClient.respond(`Hello ${this.name}`)
108// ^ -- Calling 'respond' on the 'MessageClient' will
109// send a message back to wherever that command
110// is invoked from (eg. a DM with @atomist in Slack)
111 .then(() => {
112 return Promise.resolve({ code: 0 });
113// ^ -- Command handlers are expected to return a
114// 'Promise' of type 'HandlerResult' which
115// just defines a return code. Nonzero
116// return codes indicate errors.
117 });
118 }
119}
120```
121
122The above declares a simple bot command that can be invoked via `@atomist hello world`. The command takes one
123parameter called `name`. The handler will respond with a simple greeting message.
124
125For more information, please see [Command Handlers](docs/CommandHandlers.md).
126
127### Event Handlers
128
129Event handlers are automations that allow handling of events based on registered GraphQL subscriptions.
130
131To create a event handler take a look at the following example:
132
133```typescript
134import { EventFired, EventHandler, HandleEvent, HandlerContext, HandlerResult }
135 from "@atomist/automation-client/Handlers";
136
137@EventHandler("Notify channel on new issue", `subscription HelloIssue {
138 Issue {
139 number
140 title
141 repo {
142 channels {
143 name
144 }
145 }
146 }
147}`)
148// ^ -- This is GraphQL subscription you want
149// to match to trigger your handler.
150// Queries can also be externalized.
151export class HelloIssue implements HandleEvent<any> {
152// ^ -- an event handler implements the 'HandleEvent'
153// interface
154
155 public handle(e: EventFired<any>, ctx: HandlerContext): Promise<HandlerResult> {
156// ^ ^ -- 'HandlerContext' gives access to
157// ^ 'MessageClient' and 'GraphClient'
158// ^ -- 'EventFired' gives you access to the data that matched the
159// subscription. Since GraphQL queries return JSON it is very easy
160// to work with the data in JavaScript/TypeScript
161
162 return Promise.all(e.data.Issue.map(i =>
163 ctx.messageClient.addressChannels(`Got a new issue \`${i.number}# ${i.title}\``,
164// ^ -- besides responding, you can address users and
165// channels in Slack by using the respective methods
166// on 'MessageClient'
167
168 i.repo.channels.map(c => c.name))))
169// ^ -- in our correlated data model, repositories can be mapped to
170// channels in a chat team. This will effectively send a message
171// into each mapped channel
172 .then(() => {
173 return Promise.resolve({ code: 0 });
174// ^ -- Event handlers are expected to return a
175// 'HandlerResult'. Nonzero code indicate
176// error occurred
177 });
178 }
179}
180```
181
182This event handler registers a GraphQL subscription on the `Issue` type. On `Issue` events the handler will
183send a simple message back to the associated slack team.
184
185For more information, please see [Event Handlers](docs/EventHandlers.md).
186
187### Register Handlers
188
189In order to register your handlers with the automation-client, please create a file called `atomist.config.ts` and put
190the following contents into it:
191
192```typescript
193import { Configuration } from "@atomist/automation-client/configuration";
194
195import { HelloWorld } from "./commands/HelloWorld";
196import { HelloIssue } from "./events/HelloIssue";
197
198export const configuration: Configuration = {
199// ^ -- 'Configuration' defines all configuration options
200
201 name: "your_module_name",
202// ^ -- each automation-client should have a unique name
203
204 version: "0.0.1",
205// ^ -- and a semver version
206
207 teamIds: ["T29E48P34"],
208// ^ -- the ids of your chat teams which you can get by running '@atomist pwd'
209// leave empty to use your user defaults saved by atomist-config
210
211 commands: [
212// ^ -- register all your command handlers
213 () => new HelloWorld(),
214 ],
215
216 events: [
217 () => new HelloIssue(),
218 ],
219// ^ -- the same for event handlers
220
221 token: process.env.GITHUB_TOKEN || "34563sdf......................wq455eze",
222// ^ -- configure a GitHub personal access token with read:org scope; this is used to
223// authenticate the automation-client with Atomist to make sure the client should
224// be granted access to the ingested data and chat team; leave null/undefined
225// to use your user default saved by atomist-config
226};
227```
228
229This file allows you to register your handlers as well as to specify name and version for your automation-client.
230
231## Running the Automation-Client
232
233There are several ways you can run your automation-client and have it connect to Atomist API.
234
235### Running Locally
236
237To start up the client locally and have it listen to incoming events, just run:
238
239```
240$ atomist start
241```
242
243### Pushing to Cloud Foundry
244
245To prepare for your automation-client to run on any Cloud Foundry
246instance, please make sure that you have an account on an instance of
247Cloud Foundry and that you have the Cloud Foundry CLI installed,
248configured and logged in.
249
250First you need to create a `manifest.yml` in the root of your node
251project. Put the following minimum content into the file:
252
253```
254
255applications:
256- name: YOUR_APP_NAME
257 command: $(npm bin)/atomist-client
258 memory: 128M
259 buildpack: https://github.com/cloudfoundry/nodejs-buildpack
260 env:
261 GITHUB_TOKEN: <your GITHUB_TOKEN>
262 SUPPRESS_NO_CONFIG_WARNING: true
263```
264
265There more recommended ways for getting your `GITHUB_TOKEN` into your automation-client instance.
266Take a look at [`cfenv`](https://www.npmjs.com/package/cfenv) for example
267
268Next please add an `"engines"` top-level entry to your `package.json`
269like the following:
270
271```javascript
272 "engines": {
273 "node": "8.x.x",
274 "npm": "5.x.x"
275 }
276```
277
278Now you're ready to `cf push` your automation server to Cloud Foundry:
279
280```
281$ cf push
282```
283
284## REST APIs
285
286When starting up, the `automation-client` exposes a couple of endpoints that can be accessed via HTTP.
287
288### Authentication
289
290The endpoints are protected by HTTP Basic Auth or token-based authentication. When starting the client, you'll see
291a log message of the following format:
292
293```
2942017-09-20T08:22:32.789Z - info : Auto-generated credentials for web endpoints are user 'admin' and password '4d6390d1-de5c-6764-a078-7308503ddba5'
295```
296
297By default the automation-client auto-generates some credentials for you use. To configure your own credentials, change
298`atomist.config.ts` and put a following section in:
299
300```typescript
301export const configuration: Configuration = {
302 ...
303 http: {
304 enabled: true,
305 auth: {
306 basic: {
307 enabled: true,
308 username: "some user",
309 password: "some password",
310 },
311 },
312 },
313};
314```
315
316### Endpoints
317
318#### GET Management Endpoints
319
320| Path | Description |
321|-------|-------------|
322| `/metrics` | exposes metrics around command, event handler executions |
323| `/health` | endpoint that exposes health information of the automation client |
324| `/registration` | metadata of all available automations |
325| `/info` | exposes information about this automation client |
326| `/log/commands` | all incoming request for running command handlers |
327| `/log/events` | all incoming events for event handlers |
328| `/log/messages` | all outgoing messages sent by handlers |
329
330As an example, here is an a command to get the current metrics:
331
332```
333$ curl -X GET \
334 http://localhost:2866/metrics \
335 -H 'authorization: Bearer 34563sdf......................wq455eze"' \
336 -H 'content-type: application/json'
337```
338
339The above endpoints are all HTTP GET and take bearer and basic auth per default. See below for more details about
340authentication.
341
342#### Invoking a command handler
343
344Command handlers can be invoked via a HTTP POST with the following payload:
345
346```
347$ curl -X POST \
348 http://localhost:2866/command \
349 -H 'content-type: application/json' \
350 -H 'authorization: Bearer 34563sdf......................wq455eze"'
351 -d '{
352 "parameters": [{
353 "name": "name",
354 "value": "cd"
355 }],
356 "mapped_parameters": [{
357 "name": "sender",
358 "value": "kipz"
359 },{
360 "name": "userName",
361 "value": "cd"
362 }],
363 "secrets": [{
364 "uri": "github://user_token?scopes=repo",
365 "value":"4...d"
366 }],
367 "command": "HelloWorld",
368 "correlation_id": "6cb72bf7-77b4-4939-b892-00000701fa53",
369 "team": {
370 "id": "T1L0VDKJP",
371 "name": "Atomist QA"
372 },
373 "api_version": "1"
374 }'
375```
376
377## Support
378
379General support questions should be discussed in the `#support`
380channel on our community Slack team
381at [atomist-community.slack.com][slack].
382
383If you find a problem, please create an [issue][].
384
385[issue]: https://github.com/atomist/automation-client-ts/issues
386
387## Development
388
389You will need to install [node][] to build and test this project.
390
391To run tests, define a GITHUB_TOKEN to any valid token that has repo access. The tests
392will create and delete repositories.
393
394Define GITHUB_VISIBILITY=public if you want these to be public; default is private.
395You'll get a 422 response from repo creation if you don't pay for private repos.
396
397### Build and Test
398
399Command | Reason
400------- | ------
401`npm install` | install all the required packages
402`npm run build` | lint, compile, and test
403`npm start` | start the Atomist automation client
404`npm run autostart` | run the client, refreshing when files change
405`npm run lint` | run tslint against the TypeScript
406`npm run compile` | compile all TypeScript into JavaScript
407`npm test` | run tests and ensure everything is working
408`npm run autotest` | run tests continuously
409`npm run clean` | remove stray compiled JavaScript files and build directory
410
411### Release
412
413To create a new release of the project, we push a button on the Atomist lifecycle message
414in the #automation-client-ts [channel](https://atomist-community.slack.com/messages/C74J6MFL0/) in Atomist Community Slack.
415
416---
417
418Created by [Atomist][atomist].
419Need Help? [Join our Slack team][slack].
420
421[atomist]: https://atomist.com/ (Atomist - Development Automation)
422[slack]: https://join.atomist.com/ (Atomist Community Slack)