-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
146 lines (138 loc) · 3.87 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* Lambda function that executes standard, a static file linter.
*/
const tar = require('tar')
const zlib = require('zlib')
const tmp = require('tmp')
const fs = require('fs')
const exec = require('child_process').exec
const AWS = require('aws-sdk')
const jwt = require('jsonwebtoken')
const GitHubApi = require('github')
const request = require('request')
const github = new GitHubApi()
const CMD = 'standard'
const FULL_CMD = '/var/task/node_modules/standard/bin/cmd.js'
const BUCKET = process.env.BUCKET
const PEM = process.env.PEM
const INTEGRATION_ID = process.env.INTEGRATION_ID
const STANDARD = 'JavaScript Standard Style'
function getHook (event) {
return JSON.parse(event['Records'][0]['Sns']['Message'])
}
function getToken (installationId, callback) {
'use strict'
let now = Math.round((new Date()).getTime() / 1000)
let exp = 300
let payload = {
// issued at time
'iat': now,
// JWT expiration time
'exp': now + exp,
// Integration's GitHub identifier
'iss': INTEGRATION_ID
}
let bearer = jwt.sign(payload, PEM, {algorithm: 'RS256'})
github.authenticate({
type: 'integration',
token: bearer
})
github.integrations.createInstallationToken({installation_id: installationId}, (err, res) => {
if (err) {
console.error(err)
return
}
callback(res.data.token)
})
}
function runProcess (owner, repo, sha, codePath, token) {
github.authenticate({
type: 'token',
token: token
})
let statusOptions = {
owner: owner,
repo: repo,
sha: sha,
state: 'pending',
context: STANDARD
}
github.repos.createStatus(statusOptions)
exec(FULL_CMD, {
cwd: codePath
}, (error, stdout, stderr) => {
let s3 = new AWS.S3()
let key = `${CMD}/${owner}/${repo}/${sha}.log`
let params = {
Bucket: BUCKET,
Key: key,
Body: stdout + stderr,
ACL: 'public-read',
ContentType: 'text/plain'
}
s3.putObject(params, (err, data) => {
if (err) console.error(err, err.stack)
})
statusOptions.target_url = `https://${BUCKET}.s3.amazonaws.com/${key}`
if (error) {
statusOptions.state = 'failure'
statusOptions.description = `${CMD} failed!`
} else {
statusOptions.state = 'success'
statusOptions.description = `${CMD} succeeded!`
}
github.repos.createStatus(statusOptions)
})
}
function downloadCode (owner, repo, sha, token) {
let options = {
url: `https://api.github.com/repos/${owner}/${repo}/tarball/${sha}`,
headers: {
'Authorization': `token ${token}`,
'User-Agent': 'request'
},
followAllRedirects: true
}
tmp.dir((err, path, cleanupCallback) => {
if (err) {
console.error(err)
return
}
request.get(options).on('error', console.error)
.pipe(zlib.Unzip()).on('error', console.error)
.pipe(tar.x({path: path})).on('error', console.error)
.on('end', () => {
fs.readdir(path, (err, files) => {
if (err) {
console.error(err)
return
}
runProcess(owner, repo, sha, `${path}/${files[0]}`, token)
})
})
})
}
function parseHook (hook) {
let repo = hook['repository']['name']
let owner = hook['repository']['owner']['login']
let sha
// Hooks is push event
if ('head_commit' in hook) {
sha = hook['head_commit']['id']
} else {
// Hook is pull request event
let codeHasChanged = hook['action'] in ['opened', 'edited', 'reopened']
let isOwner = hook['pull_request']['user']['login'] === owner
if (codeHasChanged && !isOwner) {
sha = hook['pull_request']['head']['sha']
}
}
return [owner, repo, sha]
}
exports.handle = (e, ctx, cb) => {
let hook = getHook(e)
let [owner, repo, sha] = parseHook(hook)
if (sha === undefined) return
let installationId = hook['installation']['id']
getToken(installationId, (token) => { downloadCode(owner, repo, sha, token) })
}