Skip to content

Commit 859841f

Browse files
author
Nicolas Garnier
committed
Polishing, simplifying and Adding README to the GitHub to Slack sample
Change-Id: I5b935399391ead5d125b69a592344471f61523b7
1 parent 5440151 commit 859841f

File tree

5 files changed

+95
-38
lines changed

5 files changed

+95
-38
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ Uses a Firebase Storage trigger.
6969
Demonstrates how to automatically generate a thumbnail for images that are uploaded to Firebase Storage.
7070
Uses a Firebase Storage trigger.
7171

72+
### [Post GitHUb commits to Slack channel](/github-to-slack)
73+
74+
Demonstrates hows how to automatically post GitHub commits to a Slack channel using an HTTPS triggered Function.
75+
7276
### [Automatically Moderate Images](/moderate-images)
7377

7478
Demonstrates how to automatically moderate offensive images that are uploaded to Firebase Storage by using the Google Cloud Vision API to detect offensive images and ImageMagick to blur these images.

github-to-slack/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Post GitHUb commits to Slack channel.
2+
3+
This sample shows how to automatically post GitHub commits to a Slack channel using an HTTPS Cloud Function.
4+
5+
Further reading:
6+
- Slack Webhooks API: https://api.slack.com/incoming-webhooks
7+
- Firebase SDK: https://firebase.google.com/docs/functions
8+
- GitHUb Webhooks: https://developer.github.com/webhooks/creating/
9+
10+
## Functions Code
11+
12+
See file [functions/index.js](functions/index.js) for the code.
13+
14+
Handling the Google Actions requests is done using the [Google Actions SDK](https://www.npmjs.com/package/actions-on-google).
15+
16+
The dependencies are listed in [functions/package.json](functions/package.json).
17+
18+
19+
## Deploy and test
20+
21+
To test this sample action:
22+
23+
- Create a Firebase Project using the [Firebase Developer Console](https://console.firebase.google.com)
24+
- Configure this sample to use your project using `firebase --use add` and select your project.
25+
- [Add a WebHook to your GitHub repo](https://help.github.com/articles/about-webhooks/) with the following settings:
26+
- Payload URL: `https://us-central1-<FIREBASE_PROJECT_ID>.cloudfunctions.net/githubWebhook`
27+
- Content type: `application/json`
28+
- Secret: `A_SECRET_YOU_DEFINE`
29+
- Which events would you like to trigger this webhook? `Just the push event.`
30+
- [Add an **Incomming Webhook**](https://my.slack.com/services/new/incoming-webhook/) to your Slack channel and take note of the **Webhook URL**.
31+
- Set the `slack.webhook_url` and `github.secret` Google Cloud environment variables to match the email and password of the Gmail account used to send emails. For this use:
32+
```bash
33+
firebase functions:config:set slack.webhook_url="https://hooks.slack.com/services/..." github.secret="A_SECRET_YOU_DEFINED_WHEN_SETTING_UP_THE_GITHUB_WEBHOOK"
34+
```
35+
- Deploy your project using `firebase deploy`
36+
- Make your action available for testing using the `gactions preview action.json`
37+
- Test your Action on the [Google Home Web Simulator](https://g.co/actionswebsim) by saying "Talk to My Action"

github-to-slack/firebase.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

github-to-slack/functions/index.js

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,64 @@
1-
const pubsub = require('@google-cloud/pubsub')(functions.config().firebase);
2-
const githubTopic = functions.config().github.topic;
1+
/**
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
'use strict';
17+
18+
const functions = require('firebase-functions');
319
const rp = require('request-promise');
20+
const crypto = require('crypto');
421

5-
exports.githubWebhook = functions.https.onRequest((request, response) => {
22+
/**
23+
* Webhook that will be called each time there is a new GitHub commit and will post a message to
24+
* Slack.
25+
*/
26+
exports.githubWebhook = functions.https.onRequest((req, res) => {
627
const cipher = 'sha1';
7-
const signature = request.headers['x-hub-signature'];
8-
const hmac = require('crypto')
9-
.createHmac(cipher, functions.config().github.secret)
10-
.update(JSON.stringify(request.body, null, 2))
11-
.digest('hex');
28+
const signature = req.headers['x-hub-signature'];
29+
30+
// TODO: Configure the `github.secret` Google Cloud environment variables.
31+
const hmac = crypto.createHmac(cipher, functions.config().github.secret)
32+
// The JSON body is automatically parsed by Cloud Functions so we re-stringify it.
33+
.update(JSON.stringify(req.body, null, 0))
34+
.digest('hex');
1235
const expectedSignature = `${cipher}=${hmac}`;
1336

14-
// Skipping verification, since JSON.stringify fails hmac, need the raw post
15-
if (true || signature === expectedSignature) {
16-
pubsub.topic(githubTopic).publish(
17-
request.body,
18-
(err, messageIds, apiResponse) => {
19-
if (err) {
20-
console.error(err);
21-
response.status(500).send('Something went wrong.');
22-
} else {
23-
response.status(200).send('');
24-
}
25-
}
26-
);
37+
// Check that the body of the request has been signed with the GitHub Secret.
38+
if (signature === expectedSignature) {
39+
postToSlack(req.body.compare, req.body.commits.length, req.body.repository).then(() => {
40+
res.end();
41+
}).catch(error => {
42+
console.error(error);
43+
res.status(500).send('Something went wrong while posting the message to Slack.');
44+
});
2745
} else {
28-
console.error(`x-hub-signature ${signature} did not match ${expectedSignature}`);
29-
response.status(403).send('Your x-hub-signature\'s bad and you should feel bad!');
46+
console.error('x-hub-signature', signature, 'did not match', expectedSignature);
47+
res.status(403).send('Your x-hub-signature\'s bad and you should feel bad!');
3048
}
3149
});
3250

33-
34-
exports.githubAnnouncer = functions.pubsub.topic(githubTopic).onPublish(event => {
35-
const payload = JSON.parse(event.data.json.payload);
36-
if (payload.ref === null) { return null; }
37-
const commits = payload.commits.length;
38-
const repo = payload.repository;
39-
const url = payload.compare;
51+
/**
52+
* Post a message to Slack about the new GitHub commit.
53+
*/
54+
function postToSlack(url, commits, repo) {
4055
return rp({
4156
method: 'POST',
42-
uri: functions.config().slack.webhookurl,
57+
// TODO: Configure the `slack.webhook_url` Google Cloud environment variables.
58+
uri: functions.config().slack.webhook_url,
4359
body: {
44-
text: `<${url}|${commits} new commit${commits > 1 ? 's' : ''}> pushed to <${repo.url}|${repo.name}>.`
60+
text: `<${url}|${commits} new commit${commits > 1 ? 's' : ''}> pushed to <${repo.url}|${repo.full_name}>.`
4561
},
4662
json: true
4763
});
48-
});
64+
}
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
{
2-
"name": "functions",
3-
"description": "Firebase Functions",
2+
"name": "github-to-slack-functions",
3+
"description": "Firebase Functions that posts new GitHub commits to a Slack channel.",
44
"dependencies": {
5-
"@google-cloud/pubsub": "^0.8.2",
6-
"firebase-admin": "^4.0.5",
5+
"crypto": "0.0.3",
6+
"firebase-admin": "^4.1.2",
77
"firebase-functions": "https://storage.googleapis.com/firebase-preview-drop/node/firebase-functions/firebase-functions-preview.latest.tar.gz",
88
"request": "^2.80.0",
99
"request-promise": "^4.1.1"
1010
}
1111
}
12-

0 commit comments

Comments
 (0)