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