Browse Source

Polishing, simplifying and Adding README to the GitHub to Slack sample

Change-Id: I5b935399391ead5d125b69a592344471f61523b7
katowulf-pr-tpl
Nicolas Garnier 8 years ago
parent
commit
859841f57c
  1. 4
      README.md
  2. 37
      github-to-slack/README.md
  3. 1
      github-to-slack/firebase.json
  4. 82
      github-to-slack/functions/index.js
  5. 9
      github-to-slack/functions/package.json

4
README.md

@ -69,6 +69,10 @@ Uses a Firebase Storage trigger.
Demonstrates how to automatically generate a thumbnail for images that are uploaded to Firebase Storage.
Uses a Firebase Storage trigger.
### [Post GitHUb commits to Slack channel](/github-to-slack)
Demonstrates hows how to automatically post GitHub commits to a Slack channel using an HTTPS triggered Function.
### [Automatically Moderate Images](/moderate-images)
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.

37
github-to-slack/README.md

@ -0,0 +1,37 @@
# Post GitHUb commits to Slack channel.
This sample shows how to automatically post GitHub commits to a Slack channel using an HTTPS Cloud Function.
Further reading:
- Slack Webhooks API: https://api.slack.com/incoming-webhooks
- Firebase SDK: https://firebase.google.com/docs/functions
- GitHUb Webhooks: https://developer.github.com/webhooks/creating/
## Functions Code
See file [functions/index.js](functions/index.js) for the code.
Handling the Google Actions requests is done using the [Google Actions SDK](https://www.npmjs.com/package/actions-on-google).
The dependencies are listed in [functions/package.json](functions/package.json).
## Deploy and test
To test this sample action:
- Create a Firebase Project using the [Firebase Developer Console](https://console.firebase.google.com)
- Configure this sample to use your project using `firebase --use add` and select your project.
- [Add a WebHook to your GitHub repo](https://help.github.com/articles/about-webhooks/) with the following settings:
- Payload URL: `https://us-central1-<FIREBASE_PROJECT_ID>.cloudfunctions.net/githubWebhook`
- Content type: `application/json`
- Secret: `A_SECRET_YOU_DEFINE`
- Which events would you like to trigger this webhook? `Just the push event.`
- [Add an **Incomming Webhook**](https://my.slack.com/services/new/incoming-webhook/) to your Slack channel and take note of the **Webhook URL**.
- 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:
```bash
firebase functions:config:set slack.webhook_url="https://hooks.slack.com/services/..." github.secret="A_SECRET_YOU_DEFINED_WHEN_SETTING_UP_THE_GITHUB_WEBHOOK"
```
- Deploy your project using `firebase deploy`
- Make your action available for testing using the `gactions preview action.json`
- Test your Action on the [Google Home Web Simulator](https://g.co/actionswebsim) by saying "Talk to My Action"

1
github-to-slack/firebase.json

@ -0,0 +1 @@
{}

82
github-to-slack/functions/index.js

@ -1,48 +1,64 @@
const pubsub = require('@google-cloud/pubsub')(functions.config().firebase);
const githubTopic = functions.config().github.topic;
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const functions = require('firebase-functions');
const rp = require('request-promise');
const crypto = require('crypto');
exports.githubWebhook = functions.https.onRequest((request, response) => {
/**
* Webhook that will be called each time there is a new GitHub commit and will post a message to
* Slack.
*/
exports.githubWebhook = functions.https.onRequest((req, res) => {
const cipher = 'sha1';
const signature = request.headers['x-hub-signature'];
const hmac = require('crypto')
.createHmac(cipher, functions.config().github.secret)
.update(JSON.stringify(request.body, null, 2))
.digest('hex');
const signature = req.headers['x-hub-signature'];
// TODO: Configure the `github.secret` Google Cloud environment variables.
const hmac = crypto.createHmac(cipher, functions.config().github.secret)
// The JSON body is automatically parsed by Cloud Functions so we re-stringify it.
.update(JSON.stringify(req.body, null, 0))
.digest('hex');
const expectedSignature = `${cipher}=${hmac}`;
// Skipping verification, since JSON.stringify fails hmac, need the raw post
if (true || signature === expectedSignature) {
pubsub.topic(githubTopic).publish(
request.body,
(err, messageIds, apiResponse) => {
if (err) {
console.error(err);
response.status(500).send('Something went wrong.');
} else {
response.status(200).send('');
}
}
);
// Check that the body of the request has been signed with the GitHub Secret.
if (signature === expectedSignature) {
postToSlack(req.body.compare, req.body.commits.length, req.body.repository).then(() => {
res.end();
}).catch(error => {
console.error(error);
res.status(500).send('Something went wrong while posting the message to Slack.');
});
} else {
console.error(`x-hub-signature ${signature} did not match ${expectedSignature}`);
response.status(403).send('Your x-hub-signature\'s bad and you should feel bad!');
console.error('x-hub-signature', signature, 'did not match', expectedSignature);
res.status(403).send('Your x-hub-signature\'s bad and you should feel bad!');
}
});
exports.githubAnnouncer = functions.pubsub.topic(githubTopic).onPublish(event => {
const payload = JSON.parse(event.data.json.payload);
if (payload.ref === null) { return null; }
const commits = payload.commits.length;
const repo = payload.repository;
const url = payload.compare;
/**
* Post a message to Slack about the new GitHub commit.
*/
function postToSlack(url, commits, repo) {
return rp({
method: 'POST',
uri: functions.config().slack.webhookurl,
// TODO: Configure the `slack.webhook_url` Google Cloud environment variables.
uri: functions.config().slack.webhook_url,
body: {
text: `<${url}|${commits} new commit${commits > 1 ? 's' : ''}> pushed to <${repo.url}|${repo.name}>.`
text: `<${url}|${commits} new commit${commits > 1 ? 's' : ''}> pushed to <${repo.url}|${repo.full_name}>.`
},
json: true
});
});
}

9
github-to-slack/functions/package.json

@ -1,12 +1,11 @@
{
"name": "functions",
"description": "Firebase Functions",
"name": "github-to-slack-functions",
"description": "Firebase Functions that posts new GitHub commits to a Slack channel.",
"dependencies": {
"@google-cloud/pubsub": "^0.8.2",
"firebase-admin": "^4.0.5",
"crypto": "0.0.3",
"firebase-admin": "^4.1.2",
"firebase-functions": "https://storage.googleapis.com/firebase-preview-drop/node/firebase-functions/firebase-functions-preview.latest.tar.gz",
"request": "^2.80.0",
"request-promise": "^4.1.1"
}
}

Loading…
Cancel
Save