This repository was archived by the owner on Mar 17, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
Add Cloud Functions #24
Open
steffnay
wants to merge
27
commits into
master
Choose a base branch
from
functions
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
c8a20ab
added cloud functions
steffnay 8b65da1
mocked settings
steffnay 705f9c3
mocked settings
steffnay d43b5b6
mocked settings
steffnay 1ce050d
fixing util require
steffnay 5c33e2f
removed util require
steffnay 714f0cb
updated proxyquire
steffnay bb40659
updated proxyquire. again.
steffnay be743bd
removed unused from package.json, updated triage test
steffnay 2cfc3af
Update CI config.
jmdobry 0867195
Merge branch 'functions' of github.com:GoogleCloudPlatform/LabelCat i…
jmdobry c042958
Update README.md
steffnay beda025
DRYed up testing, fixed inconsistent variables, addressed PR comments
steffnay 193ae22
conflict resolved
steffnay 45234d9
changed name for default settings file
steffnay e949bcc
reverted beforeEach in functions_system_test
steffnay 2c22416
debug
steffnay 9104847
updated constants and other variable names for consistency
steffnay b5352e3
corrected variables, reverted some refctoring
steffnay 60f1526
linted
steffnay 19b9f21
Debug test
jmdobry 331a53a
Fix tests.
jmdobry 8f3b8dd
Fix lint.
jmdobry d2cf9fb
Merge branch 'master' into functions
jmdobry 05d2b90
cleaned up
steffnay 38f9f15
resolved conflict
steffnay 67cde48
added getMocks function to tests
steffnay File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| node_modules/* | ||
| functions/node_modules/* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # This file specifies files that are *not* uploaded to Google Cloud Platform | ||
| # using gcloud. It follows the same syntax as .gitignore, with the addition of | ||
| # "#!include" directives (which insert the entries of the given .gitignore-style | ||
| # file at that point). | ||
| # | ||
| # For more information, run: | ||
| # $ gcloud topic gcloudignore | ||
| # | ||
| .gcloudignore | ||
| # If you would like to upload your .git directory, .gitignore file or files | ||
| # from your .gitignore file, remove the corresponding line | ||
| # below: | ||
| .git | ||
| .gitignore | ||
|
|
||
| node_modules |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| const settings = require('./settings.json'); // eslint-disable-line node/no-missing-require | ||
| const crypto = require('crypto'); | ||
| const automl = require('@google-cloud/automl'); | ||
| const PubSub = require(`@google-cloud/pubsub`); | ||
| const octokit = require('@octokit/rest')(); | ||
| const client = new automl.v1beta1.PredictionServiceClient(); | ||
| const log = require('loglevel'); | ||
| log.setLevel('info'); | ||
|
|
||
| const PROJECT_ID = settings.PROJECT_ID; | ||
| const COMPUTE_REGION = settings.COMPUTE_REGION; | ||
| const MODEL_ID = settings.MODEL_ID; | ||
| const TOPIC_NAME = settings.TOPIC_NAME; | ||
| const SECRET_TOKEN = settings.SECRET_TOKEN; | ||
| const SCORE_THRESHOLD = 70; | ||
|
|
||
| /** | ||
| * Verifies request has come from Github and publishes | ||
| * message to specified Pub/Sub topic. | ||
| * | ||
| * @param {object} req | ||
| * @param {object} res | ||
| */ | ||
| async function handleNewIssue(req, res) { | ||
| try { | ||
| if (req.body.action !== 'opened') { | ||
| res.status(400).send('Wrong action.'); | ||
| return; | ||
| } | ||
|
|
||
| await validateRequest(req); | ||
| const messageId = await publishMessage(req); | ||
| res.status(200).send(messageId); | ||
| } catch (err) { | ||
| log.error(err.stack); | ||
| res.status(403).send({error: err.message}); | ||
| } | ||
| } | ||
|
|
||
| function validateRequest(req) { | ||
| return Promise.resolve().then(() => { | ||
| const digest = crypto | ||
| .createHmac('sha1', SECRET_TOKEN) | ||
| .update(JSON.stringify(req.body)) | ||
| .digest('hex'); | ||
| if (req.headers['x-hub-signature'] !== `sha1=${digest}`) { | ||
| const error = new Error('Unauthorized'); | ||
| error.statusCode = 403; | ||
| throw error; | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| async function publishMessage(req) { | ||
steffnay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| try { | ||
| const text = `${req.body.issue.title} ${req.body.issue.body}`; | ||
| const data = JSON.stringify({ | ||
| owner: req.body.repository.owner.login, | ||
| repo: req.body.repository.name, | ||
| number: req.body.issue.number, | ||
| text: text, | ||
| }); | ||
| const dataBuffer = Buffer.from(data); | ||
|
|
||
| const pubsubClient = new PubSub({ | ||
| PROJECT_ID: PROJECT_ID, | ||
| }); | ||
|
|
||
| const response = await pubsubClient | ||
| .topic(TOPIC_NAME) | ||
| .publisher() | ||
| .publish(dataBuffer); | ||
| return response; | ||
| } catch (err) { | ||
| log.error('ERROR:', err); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * receives message from handleNewIssue cloud function, | ||
| * runs label prediction using assigned Google AutoML Natural Language model | ||
| * @param {object} req | ||
| * @param {object} res | ||
| */ | ||
| async function triage(req) { | ||
| octokit.authenticate({ | ||
| type: 'oauth', | ||
| token: settings.SECRET_TOKEN, | ||
| }); | ||
|
|
||
| const pubSubMessage = req.data; | ||
| let issueData = Buffer.from(pubSubMessage.data, 'base64').toString(); | ||
| issueData = JSON.parse(issueData); | ||
|
|
||
| issueData.labeled = false; | ||
| let results = await predict(issueData.text); | ||
|
|
||
| if (results) { | ||
| const response = await octokit.issues.addLabels({ | ||
| owner: issueData.owner, | ||
| repo: issueData.repo, | ||
| number: issueData.number, | ||
| labels: ['bug'], | ||
| }); | ||
|
|
||
| if (response.status === 200) { | ||
| issueData.labeled = true; | ||
| } | ||
| } | ||
|
|
||
| return issueData; | ||
| } | ||
|
|
||
| async function predict(text) { | ||
| const modelFullId = client.modelPath(PROJECT_ID, COMPUTE_REGION, MODEL_ID); | ||
|
|
||
| const payload = { | ||
| textSnippet: { | ||
| content: text, | ||
| mimeType: `text/plain`, | ||
| }, | ||
| }; | ||
|
|
||
| try { | ||
| const response = await client.predict({ | ||
| name: modelFullId, | ||
| payload: payload, | ||
| params: {}, | ||
| }); | ||
|
|
||
| if (response[0].payload[1].classification.score > SCORE_THRESHOLD) { | ||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } catch (err) { | ||
| log.error(err); | ||
| } | ||
| } | ||
|
|
||
| module.exports = { | ||
| handleNewIssue, | ||
| triage, | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| { | ||
| "name": "labelcat-functions", | ||
| "engines": { | ||
| "node": ">= 8.x" | ||
| }, | ||
| "dependencies": { | ||
| "@google-cloud/automl": "^0.1.2", | ||
| "@google-cloud/pubsub": "^0.20.1", | ||
| "@octokit/rest": "^15.15.1", | ||
| "loglevel": "^1.6.1" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "secretToken": "YOUR GITHUB CLIENT ID HERE", | ||
| "projectId": "YOUR GCP PROJECT ID HERE", | ||
| "computeRegion": "YOUR GCP PROJECT COMPUTE REGION HERE", | ||
| "modelId": "YOUR AUTOML NL MODEL ID HERE", | ||
| "topicName": "YOUR PUB/SUB TOPIC NAME HERE" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.