Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Weblate automatic label #158

Merged
merged 1 commit into from
Jul 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# Serverless SiteConfig GitHub Check
# wallabag Serverless Bot

[![serverless](http://public.serverless.com/badges/v3.svg)](https://serverless.com/)
[![Build Status](https://travis-ci.org/wallabag/serverless-site-config-github-check.svg?branch=master)](https://travis-ci.org/wallabag/serverless-site-config-github-check)
[![Build Status](https://travis-ci.org/wallabag/serverless-bot.svg?branch=master)](https://travis-ci.org/wallabag/serverless-bot)

This serverless project validates PRs sent to site-config repository: [fivefilters](https://github.com/fivefilters/ftr-site-config) & [graby](https://github.com/j0k3r/graby-site-config).
This serverless project does some stuff to help the wallabag team. It:

- validates PRs sent to site-config repository: [fivefilters](https://github.com/fivefilters/ftr-site-config) & [graby](https://github.com/j0k3r/graby-site-config)
- automatically label PRs created by Weblate
- more to come!

![image](https://user-images.githubusercontent.com/62333/50344781-c0a13100-052c-11e9-9f6b-3a7cb4393262.png)

Expand All @@ -12,6 +16,7 @@ This serverless project validates PRs sent to site-config repository: [fivefilte
Available lambdas:

- **extension**: It validates each file in the diff has a `.txt` extension.
- **weblate**: It automatically label PRs created by Weblate.

## Prerequisites

Expand All @@ -37,7 +42,7 @@ By default

Configure the webhook in [the GitHub repository settings](https://developer.github.com/webhooks/creating/#setting-up-a-webhook).

- In the Payload URL, enter the URL you received after deploying. It would be something like `https://<your_url>.amazonaws.com/dev/webhook`.
- In the Payload URL, enter the URL you received after deploying. It would be something like `https://<your_url>.amazonaws.com/dev/webhook/...`.
- Choose the "application/json" in Content type.
- In the types of events to trigger the webhook, select "Let me select individual events", then select at least `Pull Requests`.

Expand Down
60 changes: 60 additions & 0 deletions functions/weblate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { client } from 'octonode'
import { validateWebhook } from './utils/github'

export async function weblate(event, context, callback) {
const githubClient = client(process.env.GITHUB_TOKEN)

const body = JSON.parse(event.body)

// when creating the webhook
if (body && ('hook' in body)) {
let response

try {
const message = validateWebhook(body)

console.log(message)

response = {
statusCode: 200,
body: message,
}
} catch (e) {
console.log(e.message)

response = {
statusCode: 500,
body: e.message,
}
}

return callback(null, response)
}

if (!(body && ('pull_request' in body))) {
return callback(null, {
statusCode: 500,
body: 'Event is not a Pull Request',
})
}

console.log(`Working on repo ${body.repository.full_name} for PR #${body.pull_request.number}`)

if (body.pull_request.user.login !== 'weblate' || body.sender.login !== 'weblate') {
return callback(null, {
statusCode: 204,
body: 'PR is not from Weblate',
})
}

await githubClient
.issue(body.repository.full_name, body.pull_request.number)
.addLabelsAsync(['Translations'])

console.log('Labelled!')

return callback(null, {
statusCode: 204,
body: 'Process finished',
})
}
2 changes: 2 additions & 0 deletions handler.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { checkExtension } from './functions/extension'
import { weblate } from './functions/weblate'

export {
checkExtension,
weblate,
}
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "serverless-site-config-github-check",
"name": "wallabag-serverless-bot",
"main": "handler.js",
"scripts": {
"test": "jest",
Expand All @@ -9,7 +9,6 @@
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.10.4",
"@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/preset-env": "^7.10.4",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
Expand Down
12 changes: 11 additions & 1 deletion serverless.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
frameworkVersion: ">=1.54.0 <2.0.0"

service: serverless-site-config-github-check
service: wallabag-serverless-bot

plugins:
- serverless-webpack
Expand Down Expand Up @@ -33,3 +33,13 @@ functions:
path: webhook/extension
method: post
cors: true

weblate:
handler: handler.weblate
description: Auto label a PR create by Weblate
events:
-
http:
path: webhook/weblate
method: post
cors: true
15 changes: 0 additions & 15 deletions tests/extension.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,6 @@ describe('Validating GitHub event', () => {

describe('Validating extension', () => {
test('fail to retrieve the diff', async () => {
client.mockReturnValue({
repo: jest.fn((params) => {
expect(params).toBe('foo/bar')

return {
statusAsync: jest.fn((commit, payload) => {
expect(commit).toBe('ee55a1223ce20c3e7cb776349cb7f8efb7b88511')
expect(payload.state).toBe('failure')
expect(payload.context).toBe('Site config - File extension check')
expect(payload.description).toEqual(expect.stringContaining('has not a txt extension'))
}),
}
}),
})

nock('http://git.hub')
.get('/diff')
.reply(404)
Expand Down
181 changes: 181 additions & 0 deletions tests/weblate.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { client } from 'octonode'
import { weblate } from '../functions/weblate'

jest.mock('octonode')

describe('Validating GitHub event', () => {
test('bad event body', async () => {
const callback = jest.fn()

await weblate({ body: '{}' }, {}, callback)

expect(callback).toHaveBeenCalledTimes(1)
expect(callback).toHaveBeenCalledWith(null, {
body: 'Event is not a Pull Request',
statusCode: 500,
})
})

test('hook event does not include PR', async () => {
const callback = jest.fn()
const githubEvent = {
zen: 'Speak like a human.',
hook_id: 1,
hook: {
events: [
'issue',
'push',
],
},
repository: {
full_name: '20minutes/serverless-github-check',
},
sender: {
login: 'diego',
},
}

await weblate({ body: JSON.stringify(githubEvent) }, {}, callback)

expect(callback).toHaveBeenCalledTimes(1)
expect(callback).toHaveBeenCalledWith(null, {
body: 'This webhook needs the "pull_request" event. Please tick it.',
statusCode: 500,
})
})

test('hook event is ok', async () => {
const callback = jest.fn()
const githubEvent = {
zen: 'Speak like a human.',
hook_id: 1,
hook: {
events: [
'pull_request',
'push',
],
},
repository: {
full_name: '20minutes/serverless-github-check',
},
sender: {
login: 'diego',
},
}

await weblate({ body: JSON.stringify(githubEvent) }, {}, callback)

expect(callback).toHaveBeenCalledTimes(1)
expect(callback).toHaveBeenCalledWith(null, {
body: 'Hello diego, the webhook is now enabled for 20minutes/serverless-github-check, enjoy!',
statusCode: 200,
})
})

test('hook event for an organization is ok', async () => {
const callback = jest.fn()
const githubEvent = {
zen: 'Speak like a human.',
hook_id: 1,
hook: {
events: [
'pull_request',
'push',
],
},
organization: {
login: '20minutes',
},
sender: {
login: 'diego',
},
}

await weblate({ body: JSON.stringify(githubEvent) }, {}, callback)

expect(callback).toHaveBeenCalledTimes(1)
expect(callback).toHaveBeenCalledWith(null, {
body: 'Hello diego, the webhook is now enabled for the organization 20minutes, enjoy!',
statusCode: 200,
})
})
})

describe('Apply label', () => {
test('PR is NOT ok', async () => {
client.mockReturnValue({
issue: jest.fn((fullName, number) => {
expect(fullName).toBe('foo/bar')
expect(number).toBe(42)

return {
addLabelsAsync: jest.fn((labels) => {
expect(labels[0]).toBe('Translations')
}),
}
}),
})

const callback = jest.fn()
const githubEvent = {
pull_request: {
user: {
login: 'j0k3r',
},
number: 42,
},
repository: {
full_name: 'foo/bar',
},
sender: {
login: 'j0k3r',
},
}

await weblate({ body: JSON.stringify(githubEvent) }, {}, callback)

expect(callback).toHaveBeenCalledTimes(1)
expect(callback).toHaveBeenCalledWith(null, {
body: 'PR is not from Weblate',
statusCode: 204,
})
})
test('PR is ok', async () => {
client.mockReturnValue({
issue: jest.fn((fullName, number) => {
expect(fullName).toBe('foo/bar')
expect(number).toBe(42)

return {
addLabelsAsync: jest.fn((labels) => {
expect(labels[0]).toBe('Translations')
}),
}
}),
})

const callback = jest.fn()
const githubEvent = {
pull_request: {
user: {
login: 'weblate',
},
number: 42,
},
repository: {
full_name: 'foo/bar',
},
sender: {
login: 'weblate',
},
}

await weblate({ body: JSON.stringify(githubEvent) }, {}, callback)

expect(callback).toHaveBeenCalledTimes(1)
expect(callback).toHaveBeenCalledWith(null, {
body: 'Process finished',
statusCode: 204,
})
})
})
Loading