UNPKG

6.08 kBJavaScriptView Raw
1"use strict";
2/*
3 * MIT License
4 *
5 * Copyright (c) 2017 Choko (choko@curioswitch.org)
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26 return new (P || (P = Promise))(function (resolve, reject) {
27 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
28 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
29 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
30 step((generator = generator.apply(thisArg, _arguments || [])).next());
31 });
32};
33var __importDefault = (this && this.__importDefault) || function (mod) {
34 return (mod && mod.__esModule) ? mod : { "default": mod };
35};
36Object.defineProperty(exports, "__esModule", { value: true });
37const webhooks_1 = __importDefault(require("@octokit/webhooks"));
38const http_status_codes_1 = __importDefault(require("http-status-codes"));
39const parse_duration_1 = __importDefault(require("parse-duration"));
40const gcloud_1 = __importDefault(require("./gcloud"));
41const keymanager_1 = require("./keymanager");
42const config_1 = __importDefault(require("./config"));
43const constants_1 = require("./constants");
44const MILLIS_IN_SECOND = 1000;
45function handlePullRequest(event) {
46 return __awaiter(this, void 0, void 0, function* () {
47 if (event.action !== 'opened' && event.action !== 'synchronize') {
48 console.log('Unhandled event action: ', event.action);
49 return;
50 }
51 const pull = event.pull_request;
52 const otherBranchRemoteRef = `refs/pull/${pull.number}/head`;
53 const otherBranchLocalRef = `refs/remotes/origin/PR-${pull.number}`;
54 const baseBranchRemoteRef = `refs/heads/${pull.base.ref}`;
55 const baseBranchLocalRef = `refs/remotes/origin/${pull.base.ref}`;
56 const repo = event.repository.full_name;
57 const substitutions = {
58 _REPOSITORY_URL: pull.base.repo.clone_url,
59 _OTHER_BRANCH_REMOTE_REF: otherBranchRemoteRef,
60 _OTHER_BRANCH_LOCAL_REF: otherBranchLocalRef,
61 _BASE_BRANCH_REMOTE_REF: baseBranchRemoteRef,
62 _BASE_BRANCH_LOCAL_REF: baseBranchLocalRef,
63 [constants_1.STATUSES_URL_KEY]: pull.statuses_url,
64 [constants_1.COMMENTS_URL_KEY]: pull.comments_url,
65 };
66 const prTag = `pr.${pull.number}`;
67 const tags = [
68 `repo.${event.repository.name.replace('_', '-')}`,
69 `sender.${event.sender.login}`,
70 prTag,
71 ];
72 const google = yield gcloud_1.default();
73 const projectId = yield google.auth.getProjectId();
74 const cloudbuild = google.cloudbuild({ version: 'v1' });
75 const existingBuilds = yield cloudbuild.projects.builds.list({
76 projectId,
77 filter: `tags="${prTag}"`,
78 });
79 if (existingBuilds.data && existingBuilds.data.builds) {
80 existingBuilds.data.builds
81 .filter((build) => build.status === 'QUEUED' || build.status === 'WORKING')
82 .forEach((build) => {
83 console.log(`Found existing build ${build.id}. Cancelling.`);
84 cloudbuild.projects.builds.cancel({ projectId, id: build.id });
85 });
86 }
87 console.log(`Starting cloud build for pull request ${pull.number}.`);
88 const cloudbuildConfig = config_1.default.repos[repo].cloudbuild;
89 const sanitizedConfig = cloudbuildConfig.timeout
90 ? Object.assign({}, cloudbuildConfig, { timeout: `${parse_duration_1.default(cloudbuildConfig.timeout) /
91 MILLIS_IN_SECOND}s` }) : cloudbuildConfig;
92 yield cloudbuild.projects.builds.create({
93 projectId,
94 requestBody: Object.assign({}, sanitizedConfig, { options: Object.assign({}, sanitizedConfig.options, { substitutionOption: 'ALLOW_LOOSE' }), substitutions,
95 tags }),
96 });
97 });
98}
99function handleWebhook(req, res) {
100 return __awaiter(this, void 0, void 0, function* () {
101 const secret = yield keymanager_1.keyManager.getWebhookSecret();
102 const webhooks = new webhooks_1.default({
103 secret,
104 });
105 if (!webhooks.verify(req.rawBody.toString(), req.get('X-Hub-Signature'))) {
106 console.error('Invalid signature.');
107 res.status(http_status_codes_1.default.BAD_REQUEST).end();
108 return;
109 }
110 const event = req.body;
111 const eventType = req.get('X-GitHub-Event');
112 switch (eventType) {
113 case 'pull_request':
114 yield handlePullRequest(event);
115 break;
116 default:
117 console.log('Unhandled event type: ', eventType);
118 break;
119 }
120 res.status(http_status_codes_1.default.OK).end();
121 });
122}
123exports.default = handleWebhook;
124//# sourceMappingURL=webhook.js.map
\No newline at end of file