UNPKG

59.5 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10var __generator = (this && this.__generator) || function (thisArg, body) {
11 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13 function verb(n) { return function (v) { return step([n, v]); }; }
14 function step(op) {
15 if (f) throw new TypeError("Generator is already executing.");
16 while (_) try {
17 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18 if (y = 0, t) op = [op[0] & 2, t.value];
19 switch (op[0]) {
20 case 0: case 1: t = op; break;
21 case 4: _.label++; return { value: op[1], done: false };
22 case 5: _.label++; y = op[1]; op = [0]; continue;
23 case 7: op = _.ops.pop(); _.trys.pop(); continue;
24 default:
25 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29 if (t[2]) _.ops.pop();
30 _.trys.pop(); continue;
31 }
32 op = body.call(thisArg, _);
33 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35 }
36};
37var __read = (this && this.__read) || function (o, n) {
38 var m = typeof Symbol === "function" && o[Symbol.iterator];
39 if (!m) return o;
40 var i = m.call(o), r, ar = [], e;
41 try {
42 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
43 }
44 catch (error) { e = { error: error }; }
45 finally {
46 try {
47 if (r && !r.done && (m = i["return"])) m.call(i);
48 }
49 finally { if (e) throw e.error; }
50 }
51 return ar;
52};
53var __spread = (this && this.__spread) || function () {
54 for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
55 return ar;
56};
57var __importDefault = (this && this.__importDefault) || function (mod) {
58 return (mod && mod.__esModule) ? mod : { "default": mod };
59};
60var __importStar = (this && this.__importStar) || function (mod) {
61 if (mod && mod.__esModule) return mod;
62 var result = {};
63 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
64 result["default"] = mod;
65 return result;
66};
67var _this = this;
68Object.defineProperty(exports, "__esModule", { value: true });
69var deepmerge_1 = __importDefault(require("deepmerge"));
70var graphql_1 = require("graphql");
71var git_1 = __importDefault(require("../git"));
72var log_parse_1 = __importDefault(require("../log-parse"));
73var release_1 = __importStar(require("../release"));
74var semver_1 = __importDefault(require("../semver"));
75var logger_1 = require("../utils/logger");
76var make_commit_from_msg_1 = __importDefault(require("./make-commit-from-msg"));
77var constructor = jest.fn();
78var getGitLog = jest.fn();
79var graphql = jest.fn();
80var getPr = jest.fn();
81var getPullRequest = jest.fn();
82var getLatestRelease = jest.fn();
83var getSha = jest.fn();
84var createStatus = jest.fn();
85var getProject = jest.fn();
86var createComment = jest.fn();
87var changedPackages = jest.fn();
88var getCommitsForPR = jest.fn();
89var getUserByEmail = jest.fn();
90var getUserByUsername = jest.fn();
91var getProjectLabels = jest.fn();
92var createLabel = jest.fn();
93var updateLabel = jest.fn();
94var getPullRequests = jest.fn();
95var getLatestReleaseInfo = jest.fn();
96var searchRepo = jest.fn();
97var getCommitDate = jest.fn();
98var getFirstCommit = jest.fn();
99getProject.mockResolvedValue({
100 html_url: 'https://github.com/web/site'
101});
102var mockLabels = function (labels) { return ({
103 data: { labels: labels.map(function (label) { return ({ name: label }); }) }
104}); };
105// @ts-ignore
106jest.mock('../git.ts', function () { return function () {
107 var args = [];
108 for (var _i = 0; _i < arguments.length; _i++) {
109 args[_i] = arguments[_i];
110 }
111 constructor.apply(void 0, __spread(args));
112 return {
113 options: { owner: 'test', repo: 'test', version: '1.0.0' },
114 graphql: graphql,
115 getGitLog: getGitLog,
116 getPr: getPr,
117 getLatestRelease: getLatestRelease,
118 getPullRequest: getPullRequest,
119 getSha: getSha,
120 createStatus: createStatus,
121 createComment: createComment,
122 getProject: getProject,
123 changedPackages: changedPackages,
124 getCommitsForPR: getCommitsForPR,
125 getUserByUsername: getUserByUsername,
126 getUserByEmail: getUserByEmail,
127 getProjectLabels: getProjectLabels,
128 createLabel: createLabel,
129 updateLabel: updateLabel,
130 getPullRequests: getPullRequests,
131 getLatestReleaseInfo: getLatestReleaseInfo,
132 searchRepo: searchRepo,
133 getCommitDate: getCommitDate,
134 getFirstCommit: getFirstCommit
135 };
136}; });
137getGitLog.mockReturnValue([]);
138var execSpy = jest.fn();
139// @ts-ignore
140jest.mock('../utils/exec-promise.ts', function () { return function () {
141 var args = [];
142 for (var _i = 0; _i < arguments.length; _i++) {
143 args[_i] = arguments[_i];
144 }
145 return execSpy.apply(void 0, __spread(args));
146}; });
147var existsSync = jest.fn();
148var writeSpy = jest.fn();
149var readResult = '{}';
150jest.mock('fs', function () { return ({
151 // @ts-ignore
152 existsSync: function () {
153 var args = [];
154 for (var _i = 0; _i < arguments.length; _i++) {
155 args[_i] = arguments[_i];
156 }
157 return existsSync.apply(void 0, __spread(args));
158 },
159 // @ts-ignore
160 readFile: function (a, b, cb) {
161 cb(undefined, readResult);
162 },
163 // @ts-ignore
164 ReadStream: function () { return undefined; },
165 // @ts-ignore
166 WriteStream: function () { return undefined; },
167 // @ts-ignore
168 closeSync: function () { return undefined; },
169 // @ts-ignore
170 writeFile: function (file, data, cb) {
171 cb(undefined, writeSpy(file, data));
172 }
173}); });
174var logParse = new log_parse_1.default();
175var git = new git_1.default({
176 owner: 'Andrew',
177 repo: 'test',
178 token: 'MY_TOKEN'
179});
180describe('Release', function () {
181 beforeEach(function () {
182 getGitLog.mockClear();
183 getPr.mockClear();
184 writeSpy.mockClear();
185 execSpy.mockClear();
186 execSpy.mockClear();
187 createLabel.mockClear();
188 });
189 test('should use options owner, repo, and token', function () { return __awaiter(_this, void 0, void 0, function () {
190 var gh;
191 return __generator(this, function (_a) {
192 switch (_a.label) {
193 case 0:
194 gh = new release_1.default(git);
195 return [4 /*yield*/, gh.getCommits('12345')];
196 case 1:
197 _a.sent();
198 expect(constructor.mock.calls[0][0].owner).toBe('Andrew');
199 expect(constructor.mock.calls[0][0].repo).toBe('test');
200 return [2 /*return*/];
201 }
202 });
203 }); });
204 describe('getCommits', function () {
205 test('should default to HEAD', function () { return __awaiter(_this, void 0, void 0, function () {
206 var gh;
207 return __generator(this, function (_a) {
208 switch (_a.label) {
209 case 0:
210 gh = new release_1.default(git);
211 return [4 /*yield*/, gh.getCommits('12345')];
212 case 1:
213 _a.sent();
214 expect(getGitLog).toHaveBeenCalled();
215 return [2 /*return*/];
216 }
217 });
218 }); });
219 test('should use configured HEAD', function () { return __awaiter(_this, void 0, void 0, function () {
220 var gh;
221 return __generator(this, function (_a) {
222 switch (_a.label) {
223 case 0:
224 gh = new release_1.default(git);
225 return [4 /*yield*/, gh.getCommits('12345', '1234')];
226 case 1:
227 _a.sent();
228 expect(getGitLog).toHaveBeenCalled();
229 return [2 /*return*/];
230 }
231 });
232 }); });
233 test('should not resolve authors with no PR commits', function () { return __awaiter(_this, void 0, void 0, function () {
234 var commits, gh;
235 return __generator(this, function (_a) {
236 switch (_a.label) {
237 case 0:
238 commits = [
239 make_commit_from_msg_1.default('First'),
240 make_commit_from_msg_1.default('Second'),
241 make_commit_from_msg_1.default('Third')
242 ];
243 getGitLog.mockReturnValueOnce(commits);
244 gh = new release_1.default(git);
245 return [4 /*yield*/, gh.getCommits('12345', '1234')];
246 case 1:
247 _a.sent();
248 expect(getUserByUsername).not.toHaveBeenCalled();
249 return [2 /*return*/];
250 }
251 });
252 }); });
253 test('should resolve authors with PR commits', function () { return __awaiter(_this, void 0, void 0, function () {
254 var commits, gh, modifiedCommits;
255 return __generator(this, function (_a) {
256 switch (_a.label) {
257 case 0: return [4 /*yield*/, logParse.normalizeCommits([
258 make_commit_from_msg_1.default('First'),
259 make_commit_from_msg_1.default('Second (#123)', {
260 name: 'Andrew Lisowski',
261 email: 'andrew@users.noreply.github.com'
262 }),
263 make_commit_from_msg_1.default('Second (#123)', {
264 name: 'Andrew Lisowski',
265 email: 'lisowski54@gmail.com'
266 }),
267 make_commit_from_msg_1.default('Third')
268 ])];
269 case 1:
270 commits = _a.sent();
271 getGitLog.mockReturnValueOnce(commits);
272 getCommitsForPR.mockReturnValueOnce([
273 {
274 author: {
275 login: 'andrew'
276 }
277 }
278 ]);
279 getUserByUsername.mockReturnValueOnce({
280 login: 'andrew',
281 name: 'Andrew Lisowski'
282 });
283 getUserByUsername.mockReturnValueOnce({
284 login: 'andrew',
285 name: 'Andrew Lisowski'
286 });
287 getUserByEmail.mockReturnValueOnce({
288 login: 'adam',
289 name: 'Adam Dierkens'
290 });
291 getUserByEmail.mockReturnValueOnce({
292 login: 'adam',
293 name: 'Adam Dierkens'
294 });
295 gh = new release_1.default(git);
296 return [4 /*yield*/, gh.getCommits('12345', '1234')];
297 case 2:
298 modifiedCommits = _a.sent();
299 expect(getUserByUsername).toHaveBeenCalled();
300 expect(modifiedCommits).toMatchSnapshot();
301 return [2 /*return*/];
302 }
303 });
304 }); });
305 test('should be able to omit bye username', function () { return __awaiter(_this, void 0, void 0, function () {
306 var commits, gh, modifiedCommits;
307 return __generator(this, function (_a) {
308 switch (_a.label) {
309 case 0: return [4 /*yield*/, logParse.normalizeCommits([
310 make_commit_from_msg_1.default('First'),
311 make_commit_from_msg_1.default('Second (#123)', {
312 name: 'Andrew Lisowski',
313 email: 'lisowski54@gmail.com'
314 }),
315 make_commit_from_msg_1.default('Third')
316 ])];
317 case 1:
318 commits = _a.sent();
319 getGitLog.mockReturnValueOnce(commits);
320 getCommitsForPR.mockReturnValueOnce([
321 {
322 author: {
323 login: 'andrew'
324 }
325 }
326 ]);
327 getUserByUsername.mockReturnValueOnce({
328 login: 'andrew',
329 name: 'Andrew Lisowski'
330 });
331 getUserByEmail.mockReturnValueOnce({
332 login: 'adam',
333 name: 'Adam Dierkens'
334 });
335 getUserByEmail.mockReturnValueOnce({
336 login: 'adam',
337 name: 'Adam Dierkens'
338 });
339 gh = new release_1.default(git);
340 gh.hooks.onCreateLogParse.tap('test', function (parser) {
341 parser.hooks.omitCommit.tap('test', function (commit) {
342 return Boolean(commit.authors.find(function (author) { return author.username === 'adam'; }));
343 });
344 });
345 return [4 /*yield*/, gh.getCommits('12345', '1234')];
346 case 2:
347 modifiedCommits = _a.sent();
348 expect(modifiedCommits).toMatchSnapshot();
349 return [2 /*return*/];
350 }
351 });
352 }); });
353 test('should ignore rebased commits if no last release', function () { return __awaiter(_this, void 0, void 0, function () {
354 var gh, commits, _a;
355 return __generator(this, function (_b) {
356 switch (_b.label) {
357 case 0:
358 gh = new release_1.default(git);
359 getLatestReleaseInfo.mockReturnValueOnce({});
360 return [4 /*yield*/, logParse.normalizeCommits([
361 make_commit_from_msg_1.default('Second (#123)')
362 ])];
363 case 1:
364 commits = _b.sent();
365 getGitLog.mockReturnValueOnce(commits);
366 _a = expect;
367 return [4 /*yield*/, gh.getCommits('12345', '1234')];
368 case 2:
369 _a.apply(void 0, [_b.sent()]).toMatchSnapshot();
370 return [2 /*return*/];
371 }
372 });
373 }); });
374 test('should match rebased commits to PRs', function () { return __awaiter(_this, void 0, void 0, function () {
375 var gh, _a, _b, _c;
376 return __generator(this, function (_d) {
377 switch (_d.label) {
378 case 0:
379 gh = new release_1.default(git);
380 getLatestReleaseInfo.mockReturnValueOnce({
381 published_at: '2019-01-16'
382 });
383 searchRepo.mockReturnValueOnce({ items: [{ number: 123 }] });
384 getPullRequest.mockReturnValueOnce({
385 data: {
386 number: 123,
387 merge_commit_sha: '1a2b',
388 labels: [{ name: 'skip-release' }, { name: 'minor' }]
389 }
390 });
391 _b = (_a = getGitLog).mockReturnValueOnce;
392 return [4 /*yield*/, logParse.normalizeCommits([
393 make_commit_from_msg_1.default('Feature (#124)'),
394 make_commit_from_msg_1.default('I was rebased', {
395 hash: '1a2b'
396 })
397 ])];
398 case 1:
399 _b.apply(_a, [_d.sent()]);
400 _c = expect;
401 return [4 /*yield*/, gh.getCommits('12345', '1234')];
402 case 2:
403 _c.apply(void 0, [_d.sent()]).toMatchSnapshot();
404 return [2 /*return*/];
405 }
406 });
407 }); });
408 test('should match rebased commits to PRs with first commit', function () { return __awaiter(_this, void 0, void 0, function () {
409 var gh, _a, _b, _c;
410 return __generator(this, function (_d) {
411 switch (_d.label) {
412 case 0:
413 gh = new release_1.default(git);
414 getLatestReleaseInfo.mockImplementationOnce(function () {
415 throw new Error('no releases yet');
416 });
417 getCommitDate.mockReturnValueOnce('2019-01-16');
418 searchRepo.mockReturnValueOnce({ items: [{ number: 123 }] });
419 getPullRequest.mockReturnValueOnce({
420 data: {
421 number: 123,
422 merge_commit_sha: '1a2b',
423 labels: [{ name: 'skip-release' }, { name: 'minor' }]
424 }
425 });
426 _b = (_a = getGitLog).mockReturnValueOnce;
427 return [4 /*yield*/, logParse.normalizeCommits([
428 make_commit_from_msg_1.default('Feature (#124)'),
429 make_commit_from_msg_1.default('I was rebased', {
430 hash: '1a2b'
431 })
432 ])];
433 case 1:
434 _b.apply(_a, [_d.sent()]);
435 _c = expect;
436 return [4 /*yield*/, gh.getCommits('12345', '1234')];
437 case 2:
438 _c.apply(void 0, [_d.sent()]).toMatchSnapshot();
439 return [2 /*return*/];
440 }
441 });
442 }); });
443 });
444 describe('addToChangelog', function () {
445 test("creates new changelog if one didn't exist", function () { return __awaiter(_this, void 0, void 0, function () {
446 var gh;
447 return __generator(this, function (_a) {
448 switch (_a.label) {
449 case 0:
450 gh = new release_1.default(git);
451 return [4 /*yield*/, gh.addToChangelog('# My new Notes', 'klajsdlfk4lj51l43k5hj234l', 'v0.0.0')];
452 case 1:
453 _a.sent();
454 expect(writeSpy.mock.calls[0][1].includes("# My new Notes")).toBe(true);
455 return [2 /*return*/];
456 }
457 });
458 }); });
459 test("creates new changelog if one didn't exist", function () { return __awaiter(_this, void 0, void 0, function () {
460 var gh;
461 return __generator(this, function (_a) {
462 switch (_a.label) {
463 case 0:
464 gh = new release_1.default(git);
465 return [4 /*yield*/, gh.addToChangelog('# My new Notes', 'v1.0.0', 'v1.0.0')];
466 case 1:
467 _a.sent();
468 expect(writeSpy.mock.calls[0][1].includes("v1.0.1")).toBe(true);
469 return [2 /*return*/];
470 }
471 });
472 }); });
473 test('creates changelog with v in versions', function () { return __awaiter(_this, void 0, void 0, function () {
474 var gh;
475 return __generator(this, function (_a) {
476 switch (_a.label) {
477 case 0:
478 gh = new release_1.default(git, {
479 noVersionPrefix: true,
480 skipReleaseLabels: ['skip-release'],
481 labels: release_1.defaultLabelDefinition,
482 baseBranch: 'master'
483 });
484 return [4 /*yield*/, gh.addToChangelog('# My new Notes', '1.0.0', '1.0.0')];
485 case 1:
486 _a.sent();
487 expect(writeSpy.mock.calls[0][1].includes("1.0.1")).toBe(true);
488 return [2 /*return*/];
489 }
490 });
491 }); });
492 test('prepends to old changelog', function () { return __awaiter(_this, void 0, void 0, function () {
493 var gh;
494 return __generator(this, function (_a) {
495 switch (_a.label) {
496 case 0:
497 gh = new release_1.default(git);
498 existsSync.mockReturnValueOnce(true);
499 readResult = '# My old Notes';
500 return [4 /*yield*/, gh.addToChangelog('# My new Notes', 'asdfasdlkfjlkj435l2j', 'v0.0.0')];
501 case 1:
502 _a.sent();
503 expect(writeSpy.mock.calls[0][1].includes(readResult)).toBe(true);
504 return [2 /*return*/];
505 }
506 });
507 }); });
508 test('should be able to configure message', function () { return __awaiter(_this, void 0, void 0, function () {
509 var gh, message;
510 return __generator(this, function (_a) {
511 switch (_a.label) {
512 case 0:
513 gh = new release_1.default(git);
514 message = 'pony foo';
515 existsSync.mockReturnValueOnce(true);
516 readResult = '# My old Notes';
517 return [4 /*yield*/, gh.addToChangelog('# My new Notes', 'asdklfhlkh24387513', 'v0.0.0', message)];
518 case 1:
519 _a.sent();
520 expect(execSpy.mock.calls[1][1].includes("\"" + message + "\"")).toBe(true);
521 return [2 /*return*/];
522 }
523 });
524 }); });
525 });
526 describe('generateReleaseNotes', function () {
527 test('should default to HEAD', function () { return __awaiter(_this, void 0, void 0, function () {
528 var gh, _a;
529 return __generator(this, function (_b) {
530 switch (_b.label) {
531 case 0:
532 gh = new release_1.default(git);
533 _a = expect;
534 return [4 /*yield*/, gh.generateReleaseNotes('1234')];
535 case 1:
536 _a.apply(void 0, [_b.sent()]).toBe('');
537 return [2 /*return*/];
538 }
539 });
540 }); });
541 test('should use configured HEAD', function () { return __awaiter(_this, void 0, void 0, function () {
542 var gh, _a;
543 return __generator(this, function (_b) {
544 switch (_b.label) {
545 case 0:
546 gh = new release_1.default(git);
547 _a = expect;
548 return [4 /*yield*/, gh.generateReleaseNotes('1234', '123')];
549 case 1:
550 _a.apply(void 0, [_b.sent()]).toBe('');
551 return [2 /*return*/];
552 }
553 });
554 }); });
555 test('should include PR-less commits', function () { return __awaiter(_this, void 0, void 0, function () {
556 var gh, commits, _a;
557 return __generator(this, function (_b) {
558 switch (_b.label) {
559 case 0:
560 gh = new release_1.default(git);
561 commits = [
562 {
563 hash: '1',
564 authorName: 'Adam Dierkens',
565 authorEmail: 'adam@dierkens.com',
566 authors: [
567 {
568 name: 'Adam Dierkens',
569 email: 'adam@dierkens.com'
570 }
571 ],
572 subject: 'I should be included\nBut this should not.'
573 },
574 {
575 hash: '2',
576 authorName: 'Adam Dierkens',
577 authorEmail: 'adam@dierkens.com',
578 authors: [
579 {
580 name: 'Adam Dierkens',
581 email: 'adam@dierkens.com'
582 }
583 ],
584 subject: 'First Feature',
585 pullRequest: {
586 number: '1235'
587 }
588 },
589 {
590 hash: '3',
591 authorName: 'Adam Dierkens',
592 authorEmail: 'adam@dierkens.com',
593 authors: [
594 {
595 name: 'Adam Dierkens',
596 email: 'adam@dierkens.com'
597 }
598 ],
599 subject: 'Random Commit for pr 1235'
600 }
601 ];
602 getGitLog.mockReturnValueOnce(commits);
603 getCommitsForPR.mockReturnValueOnce(undefined);
604 getPr.mockReturnValueOnce(mockLabels(['minor']));
605 getCommitsForPR.mockReturnValueOnce([{ sha: '3' }]);
606 graphql.mockReturnValueOnce({
607 hash_1: { edges: [] }
608 });
609 _a = expect;
610 return [4 /*yield*/, gh.generateReleaseNotes('1234', '123')];
611 case 1:
612 _a.apply(void 0, [_b.sent()]).toMatchSnapshot();
613 return [2 /*return*/];
614 }
615 });
616 }); });
617 test('should allow user to configure section headings', function () { return __awaiter(_this, void 0, void 0, function () {
618 var gh, commits, _a;
619 return __generator(this, function (_b) {
620 switch (_b.label) {
621 case 0:
622 gh = new release_1.default(git);
623 commits = [
624 make_commit_from_msg_1.default('First (#1234)'),
625 make_commit_from_msg_1.default('Second (#1235)'),
626 make_commit_from_msg_1.default('Third (#1236)'),
627 make_commit_from_msg_1.default('Fourth (#1237)')
628 ];
629 getGitLog.mockReturnValueOnce(commits);
630 getPr.mockReturnValueOnce(mockLabels(['major']));
631 getPr.mockReturnValueOnce(mockLabels(['minor']));
632 getPr.mockReturnValueOnce(mockLabels(['documentation', 'internal']));
633 getPr.mockReturnValueOnce(mockLabels(['patch']));
634 _a = expect;
635 return [4 /*yield*/, gh.generateReleaseNotes('1234', '123')];
636 case 1:
637 _a.apply(void 0, [_b.sent()]).toMatchSnapshot();
638 return [2 /*return*/];
639 }
640 });
641 }); });
642 test('should match rebased commits to PRs', function () { return __awaiter(_this, void 0, void 0, function () {
643 var gh, _a;
644 return __generator(this, function (_b) {
645 switch (_b.label) {
646 case 0:
647 gh = new release_1.default(git);
648 getLatestReleaseInfo.mockReturnValueOnce({
649 published_at: '2019-01-16'
650 });
651 getCommitsForPR.mockReturnValueOnce(undefined);
652 // Rebased PR will have different commit SHAs than the commits in base branch
653 getCommitsForPR.mockReturnValueOnce([{ sha: '1a1a' }]);
654 searchRepo.mockReturnValueOnce({ items: [{ number: 123 }] });
655 getPr.mockReturnValueOnce(mockLabels(['minor']));
656 getPullRequest.mockReturnValueOnce({
657 data: {
658 number: 123,
659 merge_commit_sha: '1a2b',
660 labels: [{ name: 'skip-release' }, { name: 'minor' }]
661 }
662 });
663 getGitLog.mockReturnValueOnce([
664 make_commit_from_msg_1.default('Feature (#124)'),
665 make_commit_from_msg_1.default('I was rebased\n\n', {
666 hash: '1a2b'
667 }),
668 {
669 hash: '1',
670 authorName: 'Adam Dierkens',
671 authorEmail: 'adam@dierkens.com',
672 subject: 'I am a commit to master'
673 }
674 ]);
675 graphql.mockReturnValueOnce({
676 hash_1: { edges: [] }
677 });
678 _a = expect;
679 return [4 /*yield*/, gh.generateReleaseNotes('12345', '1234')];
680 case 1:
681 _a.apply(void 0, [_b.sent()]).toMatchSnapshot();
682 return [2 /*return*/];
683 }
684 });
685 }); });
686 test('should match commits with related PRs', function () { return __awaiter(_this, void 0, void 0, function () {
687 var gh, _a, _b, _c;
688 return __generator(this, function (_d) {
689 switch (_d.label) {
690 case 0:
691 gh = new release_1.default(git);
692 getLatestReleaseInfo.mockReturnValueOnce({
693 published_at: '2019-01-16'
694 });
695 getCommitsForPR.mockReturnValueOnce(undefined);
696 // Rebased PR will have different commit SHAs than the commits in base branch
697 getCommitsForPR.mockReturnValueOnce([{ sha: '1a1a' }]);
698 searchRepo.mockReturnValueOnce({ items: [{ number: 123 }] });
699 getPr.mockReturnValueOnce(mockLabels(['minor']));
700 getPullRequest.mockReturnValueOnce({
701 data: {
702 number: 123,
703 merge_commit_sha: '1a2b',
704 labels: [{ name: 'skip-release' }, { name: 'minor' }]
705 }
706 });
707 _b = (_a = getGitLog).mockReturnValueOnce;
708 return [4 /*yield*/, logParse.normalizeCommits([
709 make_commit_from_msg_1.default('Feature (#124)'),
710 {
711 hash: '1',
712 authorName: 'Adam Dierkens',
713 authorEmail: 'adam@dierkens.com',
714 subject: 'I am a commit with a related PR'
715 }
716 ])];
717 case 1:
718 _b.apply(_a, [_d.sent()]);
719 searchRepo.mockReturnValueOnce({
720 total_count: 1,
721 items: [{ labels: [{ name: 'patch' }] }]
722 });
723 _c = expect;
724 return [4 /*yield*/, gh.generateReleaseNotes('12345', '1234')];
725 case 2:
726 _c.apply(void 0, [_d.sent()]).toMatchSnapshot();
727 return [2 /*return*/];
728 }
729 });
730 }); });
731 test('should find matching PRs for shas through search', function () { return __awaiter(_this, void 0, void 0, function () {
732 var gh, _a;
733 return __generator(this, function (_b) {
734 switch (_b.label) {
735 case 0:
736 gh = new release_1.default(git);
737 getGitLog.mockReturnValueOnce([
738 make_commit_from_msg_1.default('Doom Patrol enabled', {
739 hash: '1'
740 }),
741 make_commit_from_msg_1.default('Autobots roll out!', {
742 hash: '2'
743 })
744 ]);
745 graphql.mockReturnValueOnce({
746 hash_1: {
747 edges: [
748 { node: { labels: { edges: [{ node: { name: 'major' } }] } } }
749 ]
750 }
751 });
752 // PR with no label, should become patch
753 graphql.mockReturnValueOnce({
754 hash_2: {
755 edges: [{ node: { labels: undefined } }]
756 }
757 });
758 _a = expect;
759 return [4 /*yield*/, gh.generateReleaseNotes('1234', '123')];
760 case 1:
761 _a.apply(void 0, [_b.sent()]).toMatchSnapshot();
762 return [2 /*return*/];
763 }
764 });
765 }); });
766 test('should find ignore closed prs', function () { return __awaiter(_this, void 0, void 0, function () {
767 var gh, _a;
768 return __generator(this, function (_b) {
769 switch (_b.label) {
770 case 0:
771 gh = new release_1.default(git);
772 getGitLog.mockReturnValueOnce([
773 make_commit_from_msg_1.default('Doom Patrol enabled', {
774 hash: '1'
775 }),
776 make_commit_from_msg_1.default('Autobots roll out!', {
777 hash: '2'
778 })
779 ]);
780 graphql.mockReturnValueOnce({
781 hash_1: {
782 edges: [
783 {
784 node: {
785 labels: {
786 edges: [{ node: { name: 'major', state: 'CLOSED' } }]
787 }
788 }
789 }
790 ]
791 }
792 });
793 // PR with no label, should become patch
794 graphql.mockReturnValueOnce({
795 hash_2: {
796 edges: [{ node: { labels: undefined } }]
797 }
798 });
799 _a = expect;
800 return [4 /*yield*/, gh.generateReleaseNotes('1234', '123')];
801 case 1:
802 _a.apply(void 0, [_b.sent()]).toMatchSnapshot();
803 return [2 /*return*/];
804 }
805 });
806 }); });
807 test('should include PRs merged to other PRs', function () { return __awaiter(_this, void 0, void 0, function () {
808 var gh, _a;
809 return __generator(this, function (_b) {
810 switch (_b.label) {
811 case 0:
812 gh = new release_1.default(git);
813 getGitLog.mockReturnValueOnce([
814 make_commit_from_msg_1.default('Doom (#12343)', {
815 hash: '1'
816 }),
817 make_commit_from_msg_1.default('Dino (#1235)', {
818 hash: '2'
819 }),
820 make_commit_from_msg_1.default('Foo Bar', {
821 hash: '3'
822 })
823 ]);
824 getCommitsForPR.mockReturnValue([{ sha: '2' }]);
825 getCommitsForPR.mockReturnValue([{ sha: '2' }]);
826 getCommitsForPR.mockReturnValue([{ sha: '3' }]);
827 getCommitsForPR.mockReturnValue([{ sha: '3' }]);
828 _a = expect;
829 return [4 /*yield*/, gh.generateReleaseNotes('1234', '123')];
830 case 1:
831 _a.apply(void 0, [_b.sent()]).toMatchSnapshot();
832 return [2 /*return*/];
833 }
834 });
835 }); });
836 });
837 describe('buildSearchQuery', function () {
838 test('generates a valid query', function () {
839 var query = release_1.buildSearchQuery('Andrew', 'test', [
840 make_commit_from_msg_1.default('first', { hash: 'abc123' }),
841 make_commit_from_msg_1.default('second', { hash: '3def78' })
842 ]);
843 expect(function () { return graphql_1.parse(query); }).not.toThrow();
844 expect(query).toMatchSnapshot();
845 });
846 test("doesn't generate a query without commits", function () {
847 var query = release_1.buildSearchQuery('Andrew', 'test', []);
848 expect(query).toBeUndefined();
849 });
850 });
851 describe('getSemverBump', function () {
852 test('default to patch', function () { return __awaiter(_this, void 0, void 0, function () {
853 var gh, commits, _a;
854 return __generator(this, function (_b) {
855 switch (_b.label) {
856 case 0:
857 gh = new release_1.default(git);
858 commits = [
859 make_commit_from_msg_1.default('First'),
860 make_commit_from_msg_1.default('Second'),
861 make_commit_from_msg_1.default('Third')
862 ];
863 getGitLog.mockReturnValueOnce(commits);
864 _a = expect;
865 return [4 /*yield*/, gh.getSemverBump('1234')];
866 case 1:
867 _a.apply(void 0, [_b.sent()]).toBe(semver_1.default.patch);
868 return [2 /*return*/];
869 }
870 });
871 }); });
872 test('should use higher version', function () { return __awaiter(_this, void 0, void 0, function () {
873 var gh, commits, _a;
874 return __generator(this, function (_b) {
875 switch (_b.label) {
876 case 0:
877 gh = new release_1.default(git);
878 commits = [
879 make_commit_from_msg_1.default('First (#1234)'),
880 make_commit_from_msg_1.default('Second'),
881 make_commit_from_msg_1.default('Third')
882 ];
883 getGitLog.mockReturnValueOnce(commits);
884 getPr.mockReturnValueOnce(mockLabels(['minor']));
885 _a = expect;
886 return [4 /*yield*/, gh.getSemverBump('1234', '123')];
887 case 1:
888 _a.apply(void 0, [_b.sent()]).toBe(semver_1.default.minor);
889 return [2 /*return*/];
890 }
891 });
892 }); });
893 test('should not publish a release', function () { return __awaiter(_this, void 0, void 0, function () {
894 var gh, commits, _a;
895 return __generator(this, function (_b) {
896 switch (_b.label) {
897 case 0:
898 gh = new release_1.default(git);
899 commits = [
900 make_commit_from_msg_1.default('First (#1234)'),
901 make_commit_from_msg_1.default('Second (#1235)'),
902 make_commit_from_msg_1.default('Third (#1236)')
903 ];
904 getGitLog.mockReturnValueOnce(commits);
905 getPr.mockReturnValueOnce(mockLabels(['skip-release', 'patch']));
906 getPr.mockReturnValueOnce(mockLabels(['skip-release', 'patch']));
907 getPr.mockReturnValueOnce(mockLabels(['skip-release', 'minor']));
908 _a = expect;
909 return [4 /*yield*/, gh.getSemverBump('1234', '123')];
910 case 1:
911 _a.apply(void 0, [_b.sent()]).toBe('');
912 return [2 /*return*/];
913 }
914 });
915 }); });
916 test('should publish a release', function () { return __awaiter(_this, void 0, void 0, function () {
917 var gh, commits, _a;
918 return __generator(this, function (_b) {
919 switch (_b.label) {
920 case 0:
921 gh = new release_1.default(git);
922 commits = [
923 make_commit_from_msg_1.default('First (#1234)'),
924 make_commit_from_msg_1.default('Second (#1235)'),
925 make_commit_from_msg_1.default('Third (#1236)')
926 ];
927 getGitLog.mockReturnValueOnce(commits);
928 getPr.mockReturnValueOnce(mockLabels(['patch']));
929 getPr.mockReturnValueOnce(mockLabels(['skip-release', 'patch']));
930 getPr.mockReturnValueOnce(mockLabels(['skip-release', 'minor']));
931 _a = expect;
932 return [4 /*yield*/, gh.getSemverBump('1234', '123')];
933 case 1:
934 _a.apply(void 0, [_b.sent()]).toBe(semver_1.default.minor);
935 return [2 /*return*/];
936 }
937 });
938 }); });
939 test('should default to publish a prepatch', function () { return __awaiter(_this, void 0, void 0, function () {
940 var gh, commits, _a;
941 return __generator(this, function (_b) {
942 switch (_b.label) {
943 case 0:
944 gh = new release_1.default(git);
945 commits = [
946 make_commit_from_msg_1.default('First (#1234)'),
947 make_commit_from_msg_1.default('Second (#1235)'),
948 make_commit_from_msg_1.default('Third (#1236)')
949 ];
950 getGitLog.mockReturnValueOnce(commits);
951 getPr.mockReturnValueOnce(mockLabels(['skip-release']));
952 getPr.mockReturnValueOnce(mockLabels([]));
953 getPr.mockReturnValueOnce(mockLabels([]));
954 _a = expect;
955 return [4 /*yield*/, gh.getSemverBump('1234', '123')];
956 case 1:
957 _a.apply(void 0, [_b.sent()]).toBe('');
958 return [2 /*return*/];
959 }
960 });
961 }); });
962 test('should not publish a release in onlyPublishWithReleaseLabel without label', function () { return __awaiter(_this, void 0, void 0, function () {
963 var gh, commits, _a;
964 return __generator(this, function (_b) {
965 switch (_b.label) {
966 case 0:
967 gh = new release_1.default(git, {
968 onlyPublishWithReleaseLabel: true,
969 skipReleaseLabels: [],
970 labels: release_1.defaultLabelDefinition,
971 baseBranch: 'master'
972 });
973 commits = [
974 make_commit_from_msg_1.default('First (#1234)'),
975 make_commit_from_msg_1.default('Second (#1235)'),
976 make_commit_from_msg_1.default('Third (#1236)')
977 ];
978 getGitLog.mockReturnValueOnce(commits);
979 getPr.mockReturnValueOnce(mockLabels(['patch']));
980 getPr.mockReturnValueOnce(mockLabels(['major']));
981 getPr.mockReturnValueOnce(mockLabels(['patch']));
982 _a = expect;
983 return [4 /*yield*/, gh.getSemverBump('1234', '123')];
984 case 1:
985 _a.apply(void 0, [_b.sent()]).toBe('');
986 return [2 /*return*/];
987 }
988 });
989 }); });
990 test('should publish a release in onlyPublishWithReleaseLabel with label', function () { return __awaiter(_this, void 0, void 0, function () {
991 var gh, commits, _a;
992 return __generator(this, function (_b) {
993 switch (_b.label) {
994 case 0:
995 gh = new release_1.default(git, {
996 onlyPublishWithReleaseLabel: true,
997 skipReleaseLabels: [],
998 labels: release_1.defaultLabelDefinition,
999 baseBranch: 'master'
1000 });
1001 commits = [
1002 make_commit_from_msg_1.default('First (#1234)'),
1003 make_commit_from_msg_1.default('Second (#1235)'),
1004 make_commit_from_msg_1.default('Third (#1236)')
1005 ];
1006 getGitLog.mockReturnValueOnce(commits);
1007 getPr.mockReturnValueOnce(mockLabels(['release', 'patch']));
1008 getPr.mockReturnValueOnce(mockLabels(['patch']));
1009 getPr.mockReturnValueOnce(mockLabels(['minor']));
1010 _a = expect;
1011 return [4 /*yield*/, gh.getSemverBump('1234', '123')];
1012 case 1:
1013 _a.apply(void 0, [_b.sent()]).toBe(semver_1.default.minor);
1014 return [2 /*return*/];
1015 }
1016 });
1017 }); });
1018 test('should be able to configure labels', function () { return __awaiter(_this, void 0, void 0, function () {
1019 var _a, customLabels, gh, commits, _b, _c;
1020 return __generator(this, function (_d) {
1021 switch (_d.label) {
1022 case 0:
1023 customLabels = deepmerge_1.default(release_1.defaultLabelDefinition, (_a = {},
1024 _a[semver_1.default.major] = { name: 'Version: Major' },
1025 _a[semver_1.default.minor] = { name: 'Version: Minor' },
1026 _a[semver_1.default.patch] = { name: 'Version: Patch' },
1027 _a.release = { name: 'Deploy' },
1028 _a));
1029 gh = new release_1.default(git, {
1030 onlyPublishWithReleaseLabel: true,
1031 skipReleaseLabels: [],
1032 labels: customLabels,
1033 baseBranch: 'master'
1034 });
1035 commits = [
1036 make_commit_from_msg_1.default('First (#1234)'),
1037 make_commit_from_msg_1.default('Second (#1235)'),
1038 make_commit_from_msg_1.default('Third (#1236)')
1039 ];
1040 // Test default labels do nothing
1041 getGitLog.mockReturnValueOnce(commits);
1042 getPr.mockReturnValueOnce(mockLabels(['Version: Major']));
1043 getPr.mockReturnValueOnce(mockLabels(['Version: Patch']));
1044 getPr.mockReturnValueOnce(mockLabels(['Version: Minor', 'release']));
1045 _b = expect;
1046 return [4 /*yield*/, gh.getSemverBump('1234', '123')];
1047 case 1:
1048 _b.apply(void 0, [_d.sent()]).toBe('');
1049 getGitLog.mockReturnValueOnce(commits);
1050 getPr.mockReturnValueOnce(mockLabels(['Version: Minor', 'Deploy']));
1051 getPr.mockReturnValueOnce(mockLabels(['Version: Major']));
1052 getPr.mockReturnValueOnce(mockLabels(['Version: Patch']));
1053 _c = expect;
1054 return [4 /*yield*/, gh.getSemverBump('1234', '123')];
1055 case 2:
1056 _c.apply(void 0, [_d.sent()]).toBe(semver_1.default.major);
1057 return [2 /*return*/];
1058 }
1059 });
1060 }); });
1061 });
1062 describe('addLabelsToProject', function () {
1063 test('should add labels', function () { return __awaiter(_this, void 0, void 0, function () {
1064 var _a, gh, customLabels;
1065 return __generator(this, function (_b) {
1066 switch (_b.label) {
1067 case 0:
1068 gh = new release_1.default(git);
1069 customLabels = (_a = {},
1070 _a[semver_1.default.major] = { name: '1', description: 'major' },
1071 _a[semver_1.default.minor] = { name: '2', description: 'minor' },
1072 _a[semver_1.default.patch] = { name: '3', description: 'patch' },
1073 _a);
1074 return [4 /*yield*/, gh.addLabelsToProject(customLabels)];
1075 case 1:
1076 _b.sent();
1077 expect(createLabel).toHaveBeenCalledWith(semver_1.default.major, {
1078 name: '1',
1079 description: 'major'
1080 });
1081 expect(createLabel).toHaveBeenCalledWith(semver_1.default.minor, {
1082 name: '2',
1083 description: 'minor'
1084 });
1085 expect(createLabel).toHaveBeenCalledWith(semver_1.default.patch, {
1086 name: '3',
1087 description: 'patch'
1088 });
1089 return [2 /*return*/];
1090 }
1091 });
1092 }); });
1093 test('should log that it has created the labels', function () { return __awaiter(_this, void 0, void 0, function () {
1094 var _a, mockLogger, gh, labels;
1095 return __generator(this, function (_b) {
1096 switch (_b.label) {
1097 case 0:
1098 mockLogger = logger_1.dummyLog();
1099 mockLogger.log.log = jest.fn();
1100 gh = new release_1.default(git, {
1101 skipReleaseLabels: [],
1102 labels: release_1.defaultLabelDefinition,
1103 baseBranch: 'master'
1104 }, mockLogger);
1105 labels = (_a = {},
1106 _a[semver_1.default.patch] = { name: '3', description: 'three' },
1107 _a);
1108 return [4 /*yield*/, gh.addLabelsToProject(labels)];
1109 case 1:
1110 _b.sent();
1111 expect(mockLogger.log.log).toHaveBeenCalledWith('Created labels: patch');
1112 expect(mockLogger.log.log).toHaveBeenCalledWith('\nYou can see these, and more at https://github.com/web/site/labels');
1113 return [2 /*return*/];
1114 }
1115 });
1116 }); });
1117 test('should not add old labels', function () { return __awaiter(_this, void 0, void 0, function () {
1118 var _a, gh, labels;
1119 return __generator(this, function (_b) {
1120 switch (_b.label) {
1121 case 0:
1122 gh = new release_1.default(git);
1123 labels = (_a = {},
1124 _a[semver_1.default.major] = { name: '1', description: 'major' },
1125 _a[semver_1.default.minor] = { name: '2', description: 'minor' },
1126 _a);
1127 getProjectLabels.mockReturnValueOnce(['1']);
1128 return [4 /*yield*/, gh.addLabelsToProject(labels)];
1129 case 1:
1130 _b.sent();
1131 expect(updateLabel).toHaveBeenCalledWith(semver_1.default.major, {
1132 name: '1',
1133 description: 'major'
1134 });
1135 expect(createLabel).toHaveBeenCalledWith(semver_1.default.minor, {
1136 description: 'minor',
1137 name: '2'
1138 });
1139 return [2 /*return*/];
1140 }
1141 });
1142 }); });
1143 test('should add release label in onlyPublishWithReleaseLabel mode', function () { return __awaiter(_this, void 0, void 0, function () {
1144 var gh, labels;
1145 return __generator(this, function (_a) {
1146 switch (_a.label) {
1147 case 0:
1148 gh = new release_1.default(git, {
1149 skipReleaseLabels: [],
1150 labels: release_1.defaultLabelDefinition,
1151 baseBranch: 'master'
1152 });
1153 labels = {
1154 release: { name: 'deploy', description: 'release the code' }
1155 };
1156 return [4 /*yield*/, gh.addLabelsToProject(labels)];
1157 case 1:
1158 _a.sent();
1159 expect(createLabel).not.toHaveBeenCalledWith('release', {
1160 name: 'deploy',
1161 description: 'release the code'
1162 });
1163 gh = new release_1.default(git, {
1164 onlyPublishWithReleaseLabel: true,
1165 skipReleaseLabels: [],
1166 labels: release_1.defaultLabelDefinition,
1167 baseBranch: 'master'
1168 });
1169 return [4 /*yield*/, gh.addLabelsToProject(labels)];
1170 case 2:
1171 _a.sent();
1172 expect(createLabel).toHaveBeenCalledWith('release', {
1173 name: 'deploy',
1174 description: 'release the code'
1175 });
1176 return [2 /*return*/];
1177 }
1178 });
1179 }); });
1180 test('should add skip-release label not in onlyPublishWithReleaseLabel mode', function () { return __awaiter(_this, void 0, void 0, function () {
1181 var gh, labels;
1182 return __generator(this, function (_a) {
1183 switch (_a.label) {
1184 case 0:
1185 gh = new release_1.default(git, {
1186 onlyPublishWithReleaseLabel: true,
1187 skipReleaseLabels: [],
1188 labels: release_1.defaultLabelDefinition,
1189 baseBranch: 'master'
1190 });
1191 labels = {
1192 'skip-release': { name: 'no!', description: 'Do not create a release' }
1193 };
1194 return [4 /*yield*/, gh.addLabelsToProject(labels)];
1195 case 1:
1196 _a.sent();
1197 expect(createLabel).not.toHaveBeenCalledWith('skip-release', {
1198 name: 'no!',
1199 description: 'Do not create a release'
1200 });
1201 gh = new release_1.default(git, {
1202 skipReleaseLabels: [],
1203 labels: release_1.defaultLabelDefinition,
1204 baseBranch: 'master'
1205 });
1206 return [4 /*yield*/, gh.addLabelsToProject(labels)];
1207 case 2:
1208 _a.sent();
1209 expect(createLabel).toHaveBeenCalledWith('skip-release', {
1210 description: 'Do not create a release',
1211 name: 'no!'
1212 });
1213 return [2 /*return*/];
1214 }
1215 });
1216 }); });
1217 });
1218});
1219//# sourceMappingURL=release.test.js.map
\No newline at end of file