|
1 | 1 | import * as c from 'config'; |
2 | 2 | import * as crypto from 'crypto'; |
3 | 3 | import * as mongodb from 'mongodb'; |
| 4 | +import { APIGatewayEvent } from 'aws-lambda'; |
| 5 | +import { PullRequestEvent } from '@octokit/webhooks-types'; |
4 | 6 | import { JobRepository } from '../../../src/repositories/jobRepository'; |
5 | 7 | import { ConsoleLogger } from '../../../src/services/logger'; |
6 | 8 | import { BranchRepository } from '../../../src/repositories/branchRepository'; |
| 9 | +import { RepoBranchesRepository } from '../../../src/repositories/repoBranchesRepository'; |
| 10 | +import { MetadataRepository } from '../../../src/repositories/metadataRepository'; |
| 11 | +import { UpdatedDocsRepository } from '../../../src/repositories/updatedDocsRepository'; |
7 | 12 |
|
8 | 13 | // This function will validate your payload from GitHub |
9 | 14 | // See docs at https://developer.github.com/webhooks/securing/#validating-payloads-from-github |
@@ -109,3 +114,101 @@ export const TriggerBuild = async (event: any = {}, context: any = {}): Promise< |
109 | 114 | body: 'Job Queued', |
110 | 115 | }; |
111 | 116 | }; |
| 117 | + |
| 118 | +/** |
| 119 | + * Deletes build artifacts for a given project + branch combination. |
| 120 | + * @param event |
| 121 | + */ |
| 122 | +export const MarkBuildArtifactsForDeletion = async (event: APIGatewayEvent) => { |
| 123 | + const consoleLogger = new ConsoleLogger(); |
| 124 | + const defaultHeaders = { 'Content-Type': 'text/plain' }; |
| 125 | + |
| 126 | + const ghEventType = event.headers['X-GitHub-Event']; |
| 127 | + if (ghEventType !== 'pull_request') { |
| 128 | + const errMsg = 'GitHub event type is not of type "pull_request"'; |
| 129 | + return { |
| 130 | + statusCode: 400, |
| 131 | + headers: defaultHeaders, |
| 132 | + body: errMsg, |
| 133 | + }; |
| 134 | + } |
| 135 | + |
| 136 | + if (!validateJsonWebhook(event, c.get<string>('githubDeletionSecret'))) { |
| 137 | + const errMsg = "X-Hub-Signature incorrect. Github webhook token doesn't match"; |
| 138 | + return { |
| 139 | + statusCode: 401, |
| 140 | + headers: defaultHeaders, |
| 141 | + body: errMsg, |
| 142 | + }; |
| 143 | + } |
| 144 | + |
| 145 | + if (!event.body) { |
| 146 | + const err = 'MarkBuildArtifactsForDeletion does not have a body in event payload'; |
| 147 | + consoleLogger.error('MarkBuildArtifactsForDeletion', err); |
| 148 | + return { |
| 149 | + statusCode: 400, |
| 150 | + headers: defaultHeaders, |
| 151 | + body: err, |
| 152 | + }; |
| 153 | + } |
| 154 | + |
| 155 | + let payload: PullRequestEvent | undefined; |
| 156 | + try { |
| 157 | + payload = JSON.parse(event.body) as PullRequestEvent; |
| 158 | + } catch (e) { |
| 159 | + const errMsg = 'Payload is not valid JSON'; |
| 160 | + return { |
| 161 | + statusCode: 400, |
| 162 | + headers: defaultHeaders, |
| 163 | + body: errMsg, |
| 164 | + }; |
| 165 | + } |
| 166 | + |
| 167 | + // Setting a webhook for PR events can have different actions: closed, opened, etc. |
| 168 | + // The "closed" action should occur whenever a PR is closed, regardless of merge or not. |
| 169 | + const { action } = payload; |
| 170 | + if (action !== 'closed') { |
| 171 | + const errMsg = `Unexpected GitHub action: ${action}`; |
| 172 | + return { |
| 173 | + statusCode: 400, |
| 174 | + headers: defaultHeaders, |
| 175 | + body: errMsg, |
| 176 | + }; |
| 177 | + } |
| 178 | + |
| 179 | + const { repository, pull_request: pullRequest } = payload; |
| 180 | + const branch = pullRequest.head.ref; |
| 181 | + |
| 182 | + const client = new mongodb.MongoClient(c.get('dbUrl')); |
| 183 | + |
| 184 | + try { |
| 185 | + await client.connect(); |
| 186 | + const poolDb = client.db(c.get('dbName')); |
| 187 | + const repoBranchesRepository = new RepoBranchesRepository(poolDb, c, consoleLogger); |
| 188 | + const project = (await repoBranchesRepository.getProjectByRepoName(repository.name)) as string; |
| 189 | + |
| 190 | + // Start marking build artifacts for deletion |
| 191 | + const snootyDb = client.db(c.get('snootyDbName')); |
| 192 | + const updatedDocsRepository = new UpdatedDocsRepository(snootyDb, c, consoleLogger); |
| 193 | + const metadataRepository = new MetadataRepository(snootyDb, c, consoleLogger); |
| 194 | + await Promise.all([ |
| 195 | + updatedDocsRepository.marksAstsForDeletion(project, branch), |
| 196 | + metadataRepository.marksMetadataForDeletion(project, branch), |
| 197 | + ]); |
| 198 | + } catch (e) { |
| 199 | + consoleLogger.error('MarkBuildArtifactsForDeletion', e); |
| 200 | + return { |
| 201 | + statusCode: 500, |
| 202 | + headers: defaultHeaders, |
| 203 | + body: e, |
| 204 | + }; |
| 205 | + } finally { |
| 206 | + await client.close(); |
| 207 | + } |
| 208 | + |
| 209 | + return { |
| 210 | + statusCode: 200, |
| 211 | + headers: defaultHeaders, |
| 212 | + body: 'Build data successfully marked for deletion', |
| 213 | + }; |
| 214 | +}; |
0 commit comments