UNPKG

49.8 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14 return new (P || (P = Promise))(function (resolve, reject) {
15 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
18 step((generator = generator.apply(thisArg, _arguments || [])).next());
19 });
20};
21var __generator = (this && this.__generator) || function (thisArg, body) {
22 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24 function verb(n) { return function (v) { return step([n, v]); }; }
25 function step(op) {
26 if (f) throw new TypeError("Generator is already executing.");
27 while (_) try {
28 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;
29 if (y = 0, t) op = [op[0] & 2, t.value];
30 switch (op[0]) {
31 case 0: case 1: t = op; break;
32 case 4: _.label++; return { value: op[1], done: false };
33 case 5: _.label++; y = op[1]; op = [0]; continue;
34 case 7: op = _.ops.pop(); _.trys.pop(); continue;
35 default:
36 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40 if (t[2]) _.ops.pop();
41 _.trys.pop(); continue;
42 }
43 op = body.call(thisArg, _);
44 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46 }
47};
48var __rest = (this && this.__rest) || function (s, e) {
49 var t = {};
50 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
51 t[p] = s[p];
52 if (s != null && typeof Object.getOwnPropertySymbols === "function")
53 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
54 t[p[i]] = s[p[i]];
55 return t;
56};
57var __read = (this && this.__read) || function (o, n) {
58 var m = typeof Symbol === "function" && o[Symbol.iterator];
59 if (!m) return o;
60 var i = m.call(o), r, ar = [], e;
61 try {
62 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
63 }
64 catch (error) { e = { error: error }; }
65 finally {
66 try {
67 if (r && !r.done && (m = i["return"])) m.call(i);
68 }
69 finally { if (e) throw e.error; }
70 }
71 return ar;
72};
73var __spread = (this && this.__spread) || function () {
74 for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
75 return ar;
76};
77var __importDefault = (this && this.__importDefault) || function (mod) {
78 return (mod && mod.__esModule) ? mod : { "default": mod };
79};
80var __importStar = (this && this.__importStar) || function (mod) {
81 if (mod && mod.__esModule) return mod;
82 var result = {};
83 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
84 result["default"] = mod;
85 return result;
86};
87Object.defineProperty(exports, "__esModule", { value: true });
88var dotenv_1 = __importDefault(require("dotenv"));
89var env_ci_1 = __importDefault(require("env-ci"));
90var fs_1 = __importDefault(require("fs"));
91var path_1 = __importDefault(require("path"));
92var semver_1 = require("semver");
93var config_1 = __importDefault(require("./config"));
94var git_1 = __importDefault(require("./git"));
95var init_1 = __importDefault(require("./init"));
96var main_1 = require("./main");
97var release_1 = __importStar(require("./release"));
98var semver_2 = __importStar(require("./semver"));
99var load_plugins_1 = __importDefault(require("./utils/load-plugins"));
100var logger_1 = __importDefault(require("./utils/logger"));
101var make_hooks_1 = require("./utils/make-hooks");
102var env = env_ci_1.default();
103var loadEnv = function () {
104 var envFile = path_1.default.resolve(process.cwd(), '.env');
105 if (!fs_1.default.existsSync(envFile)) {
106 return;
107 }
108 var envConfig = dotenv_1.default.parse(fs_1.default.readFileSync(envFile));
109 Object.entries(envConfig).forEach(function (_a) {
110 var _b = __read(_a, 2), key = _b[0], value = _b[1];
111 process.env[key] = value;
112 });
113};
114var Auto = /** @class */ (function () {
115 function Auto(args) {
116 var _this = this;
117 this.prefixRelease = function (release) {
118 if (!_this.release) {
119 throw _this.createErrorMessage();
120 }
121 return _this.release.options.noVersionPrefix || release.startsWith('v')
122 ? release
123 : "v" + release;
124 };
125 this.args = args;
126 this.baseBranch = args.baseBranch || 'master';
127 this.logger = logger_1.default(args.veryVerbose ? 'veryVerbose' : args.verbose ? 'verbose' : undefined);
128 this.hooks = make_hooks_1.makeHooks();
129 this.hooks.onCreateRelease.tap('Link onCreateChangelog', function (release) {
130 release.hooks.onCreateChangelog.tap('Link onCreateChangelog', function (changelog) {
131 _this.hooks.onCreateChangelog.call(changelog);
132 });
133 });
134 this.hooks.onCreateRelease.tap('Link onCreateLogParse', function (release) {
135 release.hooks.onCreateLogParse.tap('Link onCreateLogParse', function (logParse) {
136 _this.hooks.onCreateLogParse.call(logParse);
137 });
138 });
139 loadEnv();
140 }
141 /**
142 * Load the .autorc from the file system, set up defaults, combine with CLI args
143 * load the extends property, load the plugins and start the git remote interface.
144 */
145 Auto.prototype.loadConfig = function () {
146 return __awaiter(this, void 0, void 0, function () {
147 var configLoader, config, _a, _b, _c, repository, token, githubOptions;
148 return __generator(this, function (_d) {
149 switch (_d.label) {
150 case 0:
151 configLoader = new config_1.default(this.logger);
152 _b = (_a = this.hooks.modifyConfig).call;
153 _c = [{}];
154 return [4 /*yield*/, configLoader.loadConfig(this.args)];
155 case 1:
156 config = _b.apply(_a, [__assign.apply(void 0, _c.concat([(_d.sent()), { baseBranch: this.baseBranch }]))]);
157 this.logger.verbose.success('Loaded `auto` with config:', config);
158 this.config = config;
159 this.labels = config.labels;
160 this.semVerLabels = release_1.getVersionMap(config.labels);
161 this.loadPlugins(config);
162 this.hooks.beforeRun.call(config);
163 return [4 /*yield*/, this.getRepo(config)];
164 case 2:
165 repository = _d.sent();
166 token = repository && repository.token ? repository.token : process.env.GH_TOKEN;
167 if (!token || token === 'undefined') {
168 this.logger.log.error('No GitHub was found. Make sure it is available on process.env.GH_TOKEN.');
169 throw new Error('GitHub token not found!');
170 }
171 githubOptions = __assign({ owner: config.owner, repo: config.repo }, repository, { token: token, baseUrl: config.githubApi || 'https://api.github.com', graphqlBaseUrl: config.githubGraphqlApi || config.githubApi || 'https://api.github.com' });
172 this.git = this.startGit(githubOptions);
173 this.release = new release_1.default(this.git, config, this.logger);
174 this.hooks.onCreateRelease.call(this.release);
175 return [2 /*return*/];
176 }
177 });
178 });
179 };
180 /**
181 * Interactive prompt for initializing an .autorc
182 */
183 Auto.prototype.init = function (options) {
184 if (options === void 0) { options = {}; }
185 return __awaiter(this, void 0, void 0, function () {
186 return __generator(this, function (_a) {
187 switch (_a.label) {
188 case 0: return [4 /*yield*/, init_1.default(options, this.logger)];
189 case 1:
190 _a.sent();
191 return [2 /*return*/];
192 }
193 });
194 });
195 };
196 /**
197 * Create all of the user's labels on the git remote if the don't already exist
198 *
199 * @param options Options for the createLabels functionality
200 */
201 Auto.prototype.createLabels = function (options) {
202 if (options === void 0) { options = {}; }
203 return __awaiter(this, void 0, void 0, function () {
204 return __generator(this, function (_a) {
205 switch (_a.label) {
206 case 0:
207 if (!this.release || !this.labels) {
208 throw this.createErrorMessage();
209 }
210 return [4 /*yield*/, this.release.addLabelsToProject(this.labels, options)];
211 case 1:
212 _a.sent();
213 return [2 /*return*/];
214 }
215 });
216 });
217 };
218 /**
219 * Get the labels on a specific PR. Defaults to the labels of the last merged PR
220 *
221 * @param options Options for the createLabels functionality
222 */
223 Auto.prototype.label = function (_a) {
224 var pr = (_a === void 0 ? {} : _a).pr;
225 return __awaiter(this, void 0, void 0, function () {
226 var labels, pulls, lastMerged;
227 return __generator(this, function (_b) {
228 switch (_b.label) {
229 case 0:
230 if (!this.git) {
231 throw this.createErrorMessage();
232 }
233 this.logger.verbose.info("Using command: 'label'");
234 labels = [];
235 if (!!pr) return [3 /*break*/, 2];
236 return [4 /*yield*/, this.git.getPullRequests({
237 state: 'closed'
238 })];
239 case 1:
240 pulls = _b.sent();
241 lastMerged = pulls
242 .sort(function (a, b) {
243 return new Date(b.merged_at).getTime() - new Date(a.merged_at).getTime();
244 })
245 .find(function (pull) { return !!pull.merged_at; });
246 if (lastMerged) {
247 labels = lastMerged.labels.map(function (label) { return label.name; });
248 }
249 return [3 /*break*/, 4];
250 case 2: return [4 /*yield*/, this.git.getLabels(pr)];
251 case 3:
252 labels = _b.sent();
253 _b.label = 4;
254 case 4:
255 if (labels.length) {
256 console.log(labels.join('\n'));
257 }
258 return [2 /*return*/];
259 }
260 });
261 });
262 };
263 /**
264 * Create a status on a PR.
265 *
266 * @param options Options for the pr status functionality
267 */
268 Auto.prototype.pr = function (_a) {
269 var dryRun = _a.dryRun, pr = _a.pr, url = _a.url, options = __rest(_a, ["dryRun", "pr", "url"]);
270 return __awaiter(this, void 0, void 0, function () {
271 var sha, prNumber, res, target_url, error_1;
272 return __generator(this, function (_b) {
273 switch (_b.label) {
274 case 0:
275 if (!this.git) {
276 throw this.createErrorMessage();
277 }
278 sha = options.sha;
279 try {
280 prNumber = this.getPrNumber('pr', pr);
281 }
282 catch (error) {
283 // default to sha if no PR found
284 }
285 this.logger.verbose.info("Using command: 'pr'");
286 if (!(!sha && prNumber)) return [3 /*break*/, 2];
287 this.logger.verbose.info('Getting commit SHA from PR.');
288 return [4 /*yield*/, this.git.getPullRequest(prNumber)];
289 case 1:
290 res = _b.sent();
291 sha = res.data.head.sha;
292 return [3 /*break*/, 4];
293 case 2:
294 if (!!sha) return [3 /*break*/, 4];
295 this.logger.verbose.info('No PR found, getting commit SHA from HEAD.');
296 return [4 /*yield*/, this.git.getSha()];
297 case 3:
298 sha = _b.sent();
299 _b.label = 4;
300 case 4:
301 this.logger.verbose.info('Found PR SHA:', sha);
302 target_url = url;
303 if (!!dryRun) return [3 /*break*/, 9];
304 _b.label = 5;
305 case 5:
306 _b.trys.push([5, 7, , 8]);
307 return [4 /*yield*/, this.git.createStatus(__assign({}, options, { sha: sha,
308 target_url: target_url }))];
309 case 6:
310 _b.sent();
311 return [3 /*break*/, 8];
312 case 7:
313 error_1 = _b.sent();
314 throw new Error("Failed to post status to Pull Request with error code " + error_1.status);
315 case 8:
316 this.logger.log.success('Posted status to Pull Request.');
317 return [3 /*break*/, 10];
318 case 9:
319 this.logger.verbose.info('`pr` dry run complete.');
320 _b.label = 10;
321 case 10:
322 this.logger.verbose.success('Finished `pr` command');
323 return [2 /*return*/];
324 }
325 });
326 });
327 };
328 /**
329 * Check that a PR has a SEMVER label. Set a success status on the PR.
330 *
331 * @param options Options for the pr check functionality
332 */
333 Auto.prototype.prCheck = function (_a) {
334 var dryRun = _a.dryRun, pr = _a.pr, url = _a.url, options = __rest(_a, ["dryRun", "pr", "url"]);
335 return __awaiter(this, void 0, void 0, function () {
336 var target_url, prNumber, msg, sha, res, labels, labelTexts_1, releaseTag, skipReleaseTag, semverTag, description, error_2, error_3;
337 var _this = this;
338 return __generator(this, function (_b) {
339 switch (_b.label) {
340 case 0:
341 if (!this.git || !this.release || !this.semVerLabels) {
342 throw this.createErrorMessage();
343 }
344 this.logger.verbose.info("Using command: 'pr-check' for '" + url + "'");
345 target_url = url;
346 prNumber = this.getPrNumber('prCheck', pr);
347 _b.label = 1;
348 case 1:
349 _b.trys.push([1, 4, , 5]);
350 return [4 /*yield*/, this.git.getPullRequest(prNumber)];
351 case 2:
352 res = _b.sent();
353 sha = res.data.head.sha;
354 return [4 /*yield*/, this.git.getLabels(prNumber)];
355 case 3:
356 labels = _b.sent();
357 labelTexts_1 = __spread(this.semVerLabels.values());
358 releaseTag = labels.find(function (l) { return l === 'release'; });
359 skipReleaseTag = labels.find(function (l) {
360 return !!_this.release && _this.release.options.skipReleaseLabels.includes(l);
361 });
362 semverTag = labels.find(function (l) {
363 return labelTexts_1.includes(l) &&
364 !!_this.release &&
365 !_this.release.options.skipReleaseLabels.includes(l) &&
366 l !== 'release';
367 });
368 if (semverTag === undefined && !skipReleaseTag) {
369 throw new Error('No semver label!');
370 }
371 this.logger.log.success("PR is using label: " + semverTag);
372 description = void 0;
373 if (skipReleaseTag) {
374 description = 'PR will not create a release';
375 }
376 else if (releaseTag) {
377 description = "PR will create release once merged - " + semverTag;
378 }
379 else {
380 description = "CI - " + semverTag;
381 }
382 msg = {
383 description: description,
384 state: 'success'
385 };
386 return [3 /*break*/, 5];
387 case 4:
388 error_2 = _b.sent();
389 msg = {
390 description: error_2.message,
391 state: 'error'
392 };
393 return [3 /*break*/, 5];
394 case 5:
395 this.logger.verbose.info('Posting status to GitHub\n', msg);
396 if (!!dryRun) return [3 /*break*/, 10];
397 _b.label = 6;
398 case 6:
399 _b.trys.push([6, 8, , 9]);
400 return [4 /*yield*/, this.git.createStatus(__assign({}, options, msg, { target_url: target_url,
401 sha: sha }))];
402 case 7:
403 _b.sent();
404 this.logger.log.success('Posted status to Pull Request.');
405 return [3 /*break*/, 9];
406 case 8:
407 error_3 = _b.sent();
408 throw new Error("Failed to post status to Pull Request with error code " + error_3.status);
409 case 9: return [3 /*break*/, 11];
410 case 10:
411 this.logger.verbose.info('`pr-check` dry run complete.');
412 _b.label = 11;
413 case 11:
414 this.logger.verbose.success('Finished `pr-check` command');
415 return [2 /*return*/];
416 }
417 });
418 });
419 };
420 /**
421 * Comment on a PR. Only one comment will be present on the PR, Older comments are removed.
422 * You can use the "context" option to multiple comments on a PR.
423 *
424 * @param options Options for the comment functionality
425 */
426 Auto.prototype.comment = function (options) {
427 return __awaiter(this, void 0, void 0, function () {
428 var message, pr, _a, context, dryRun, deleteFlag, prNumber;
429 return __generator(this, function (_b) {
430 switch (_b.label) {
431 case 0:
432 message = options.message, pr = options.pr, _a = options.context, context = _a === void 0 ? 'default' : _a, dryRun = options.dryRun, deleteFlag = options.delete;
433 if (!this.git) {
434 throw this.createErrorMessage();
435 }
436 this.logger.verbose.info("Using command: 'comment'");
437 prNumber = this.getPrNumber('comment', pr);
438 if (!dryRun) return [3 /*break*/, 1];
439 if (deleteFlag) {
440 this.logger.log.info("Would have deleted comment on " + prNumber + " under \"" + context + "\" context");
441 }
442 else {
443 this.logger.log.info("Would have commented on " + prNumber + " under \"" + context + "\" context:\n\n" + message);
444 }
445 return [3 /*break*/, 5];
446 case 1:
447 if (!deleteFlag) return [3 /*break*/, 3];
448 return [4 /*yield*/, this.git.deleteComment(prNumber, context)];
449 case 2:
450 _b.sent();
451 _b.label = 3;
452 case 3:
453 if (!message) return [3 /*break*/, 5];
454 return [4 /*yield*/, this.git.createComment(message, prNumber, context)];
455 case 4:
456 _b.sent();
457 this.logger.log.success("Commented on PR #" + pr);
458 _b.label = 5;
459 case 5: return [2 /*return*/];
460 }
461 });
462 });
463 };
464 /**
465 * Update the body of a PR with a message. Only one message will be present in the PR,
466 * Older messages are removed. You can use the "context" option to multiple message
467 * in a PR body.
468 *
469 * @param options Options
470 */
471 Auto.prototype.prBody = function (options) {
472 return __awaiter(this, void 0, void 0, function () {
473 var message, pr, _a, context, dryRun, deleteFlag, prNumber;
474 return __generator(this, function (_b) {
475 switch (_b.label) {
476 case 0:
477 message = options.message, pr = options.pr, _a = options.context, context = _a === void 0 ? 'default' : _a, dryRun = options.dryRun, deleteFlag = options.delete;
478 if (!this.git) {
479 throw this.createErrorMessage();
480 }
481 this.logger.verbose.info("Using command: 'pr-body'");
482 prNumber = this.getPrNumber('pr-body', pr);
483 if (!dryRun) return [3 /*break*/, 1];
484 if (deleteFlag) {
485 this.logger.log.info("Would have deleted PR body on " + prNumber + " under \"" + context + "\" context");
486 }
487 else {
488 this.logger.log.info("Would have appended to PR body on " + prNumber + " under \"" + context + "\" context:\n\n" + message);
489 }
490 return [3 /*break*/, 6];
491 case 1:
492 if (!deleteFlag) return [3 /*break*/, 3];
493 return [4 /*yield*/, this.git.addToPrBody('', prNumber, context)];
494 case 2:
495 _b.sent();
496 _b.label = 3;
497 case 3:
498 if (!message) return [3 /*break*/, 5];
499 return [4 /*yield*/, this.git.addToPrBody(message, prNumber, context)];
500 case 4:
501 _b.sent();
502 _b.label = 5;
503 case 5:
504 this.logger.log.success("Updated body on PR #" + prNumber);
505 _b.label = 6;
506 case 6: return [2 /*return*/];
507 }
508 });
509 });
510 };
511 /**
512 * Calculate the version bump for the current state of the repository.
513 */
514 Auto.prototype.version = function () {
515 return __awaiter(this, void 0, void 0, function () {
516 var bump;
517 return __generator(this, function (_a) {
518 switch (_a.label) {
519 case 0:
520 this.logger.verbose.info("Using command: 'version'");
521 return [4 /*yield*/, this.getVersion()];
522 case 1:
523 bump = _a.sent();
524 console.log(bump);
525 return [2 /*return*/];
526 }
527 });
528 });
529 };
530 /**
531 * Calculate the the changelog and commit it.
532 */
533 Auto.prototype.changelog = function (options) {
534 return __awaiter(this, void 0, void 0, function () {
535 return __generator(this, function (_a) {
536 switch (_a.label) {
537 case 0:
538 this.logger.verbose.info("Using command: 'changelog'");
539 return [4 /*yield*/, this.makeChangelog(options)];
540 case 1:
541 _a.sent();
542 return [2 /*return*/];
543 }
544 });
545 });
546 };
547 /**
548 * Make a release to the git remote with the changes.
549 */
550 Auto.prototype.runRelease = function (options) {
551 if (options === void 0) { options = {}; }
552 return __awaiter(this, void 0, void 0, function () {
553 return __generator(this, function (_a) {
554 switch (_a.label) {
555 case 0:
556 this.logger.verbose.info("Using command: 'release'");
557 return [4 /*yield*/, this.makeRelease(options)];
558 case 1:
559 _a.sent();
560 return [2 /*return*/];
561 }
562 });
563 });
564 };
565 Auto.prototype.canary = function (options) {
566 if (options === void 0) { options = {}; }
567 return __awaiter(this, void 0, void 0, function () {
568 var pr, build, head, labels, version, canaryVersion, _a, newVersion, result, message, latestTag, commitsInRelease;
569 return __generator(this, function (_b) {
570 switch (_b.label) {
571 case 0:
572 if (!this.git || !this.release) {
573 throw this.createErrorMessage();
574 }
575 if ('pr' in env && 'build' in env) {
576 (pr = env.pr);
577 (build = env.build);
578 }
579 else if ('pr' in env && 'commit' in env) {
580 (pr = env.pr);
581 build = env.commit;
582 }
583 pr = options.pr ? String(options.pr) : pr;
584 build = options.build ? String(options.build) : build;
585 return [4 /*yield*/, this.release.getCommitsInRelease('HEAD^')];
586 case 1:
587 head = _b.sent();
588 labels = head.map(function (commit) { return commit.labels; });
589 version = semver_2.calculateSemVerBump(labels, this.semVerLabels, this.config) ||
590 semver_2.default.patch;
591 canaryVersion = '';
592 if (pr) {
593 canaryVersion = canaryVersion + "." + pr;
594 }
595 if (build) {
596 canaryVersion = canaryVersion + "." + build;
597 }
598 if (!!('isPr' in env)) return [3 /*break*/, 3];
599 _a = canaryVersion + ".";
600 return [4 /*yield*/, this.git.getSha(true)];
601 case 2:
602 canaryVersion = _a + (_b.sent());
603 _b.label = 3;
604 case 3:
605 newVersion = '';
606 if (!options.dryRun) return [3 /*break*/, 4];
607 this.logger.log.warn("Published canary identifier would be: \"-canary" + canaryVersion + "\"");
608 return [3 /*break*/, 8];
609 case 4:
610 this.logger.verbose.info('Calling canary hook');
611 return [4 /*yield*/, this.hooks.canary.promise(version, canaryVersion)];
612 case 5:
613 result = _b.sent();
614 if (typeof result === 'object') {
615 this.logger.log.warn(result.error);
616 return [2 /*return*/];
617 }
618 newVersion = result;
619 message = options.message || 'Published PR with canary version: `%v`';
620 if (!(message !== 'false' && pr)) return [3 /*break*/, 7];
621 return [4 /*yield*/, this.prBody({
622 pr: Number(pr),
623 message: message.replace('%v', newVersion),
624 context: 'canary-version'
625 })];
626 case 6:
627 _b.sent();
628 _b.label = 7;
629 case 7:
630 this.logger.log.success("Published canary version" + (newVersion ? ": " + newVersion : ''));
631 _b.label = 8;
632 case 8: return [4 /*yield*/, this.git.getLatestTagInBranch()];
633 case 9:
634 latestTag = _b.sent();
635 return [4 /*yield*/, this.release.getCommits(latestTag)];
636 case 10:
637 commitsInRelease = _b.sent();
638 return [2 /*return*/, { newVersion: newVersion, commitsInRelease: commitsInRelease }];
639 }
640 });
641 });
642 };
643 /**
644 * Run the full workflow.
645 *
646 * 1. Calculate version
647 * 2. Make changelog
648 * 3. Publish code
649 * 4. Create a release
650 */
651 Auto.prototype.shipit = function (options) {
652 if (options === void 0) { options = {}; }
653 return __awaiter(this, void 0, void 0, function () {
654 var isPR, isBaseBranch, publishInfo, _a, newVersion, commitsInRelease;
655 return __generator(this, function (_b) {
656 switch (_b.label) {
657 case 0:
658 if (!this.git || !this.release) {
659 throw this.createErrorMessage();
660 }
661 this.logger.verbose.info("Using command: 'shipit'");
662 this.hooks.beforeShipIt.call();
663 isPR = 'isPr' in env && env.isPr;
664 isBaseBranch = !isPR && 'branch' in env && env.branch === this.baseBranch;
665 if (!isBaseBranch) return [3 /*break*/, 2];
666 return [4 /*yield*/, this.publishLatest(options)];
667 case 1:
668 _a = _b.sent();
669 return [3 /*break*/, 4];
670 case 2: return [4 /*yield*/, this.canary(options)];
671 case 3:
672 _a = _b.sent();
673 _b.label = 4;
674 case 4:
675 publishInfo = _a;
676 if (!publishInfo) {
677 return [2 /*return*/];
678 }
679 newVersion = publishInfo.newVersion, commitsInRelease = publishInfo.commitsInRelease;
680 return [4 /*yield*/, this.hooks.afterShipIt.promise(newVersion, commitsInRelease)];
681 case 5:
682 _b.sent();
683 return [2 /*return*/];
684 }
685 });
686 });
687 };
688 Auto.prototype.getCurrentVersion = function (lastRelease) {
689 return __awaiter(this, void 0, void 0, function () {
690 var lastVersion;
691 var _this = this;
692 return __generator(this, function (_a) {
693 switch (_a.label) {
694 case 0:
695 this.hooks.getPreviousVersion.tap('None', function () {
696 _this.logger.veryVerbose.info('No previous release found, using 0.0.0 as previous version.');
697 return _this.prefixRelease('0.0.0');
698 });
699 return [4 /*yield*/, this.hooks.getPreviousVersion.promise(this.prefixRelease)];
700 case 1:
701 lastVersion = _a.sent();
702 if (semver_1.parse(lastRelease) &&
703 semver_1.parse(lastVersion) &&
704 semver_1.gt(lastRelease, lastVersion)) {
705 this.logger.veryVerbose.info('Using latest release as previous version');
706 return [2 /*return*/, lastRelease];
707 }
708 return [2 /*return*/, lastVersion];
709 }
710 });
711 });
712 };
713 Auto.prototype.publishLatest = function (options) {
714 return __awaiter(this, void 0, void 0, function () {
715 var version, lastRelease, commitsInRelease, newVersion, current;
716 return __generator(this, function (_a) {
717 switch (_a.label) {
718 case 0:
719 if (!this.git || !this.release) {
720 throw this.createErrorMessage();
721 }
722 return [4 /*yield*/, this.getVersion()];
723 case 1:
724 version = _a.sent();
725 if (version === '') {
726 this.logger.log.info('No version published.');
727 return [2 /*return*/];
728 }
729 return [4 /*yield*/, this.git.getLatestRelease()];
730 case 2:
731 lastRelease = _a.sent();
732 return [4 /*yield*/, this.release.getCommitsInRelease(lastRelease)];
733 case 3:
734 commitsInRelease = _a.sent();
735 return [4 /*yield*/, this.makeChangelog(options)];
736 case 4:
737 _a.sent();
738 if (!!options.dryRun) return [3 /*break*/, 9];
739 this.logger.verbose.info('Calling version hook');
740 return [4 /*yield*/, this.hooks.version.promise(version)];
741 case 5:
742 _a.sent();
743 this.logger.verbose.info('Calling after version hook');
744 return [4 /*yield*/, this.hooks.afterVersion.promise()];
745 case 6:
746 _a.sent();
747 this.logger.verbose.info('Calling publish hook');
748 return [4 /*yield*/, this.hooks.publish.promise(version)];
749 case 7:
750 _a.sent();
751 this.logger.verbose.info('Calling after publish hook');
752 return [4 /*yield*/, this.hooks.afterPublish.promise()];
753 case 8:
754 _a.sent();
755 _a.label = 9;
756 case 9: return [4 /*yield*/, this.makeRelease(options)];
757 case 10:
758 newVersion = _a.sent();
759 if (!options.dryRun) return [3 /*break*/, 12];
760 this.logger.log.warn("The version reported in the line above hasn't been incremented during `dry-run`");
761 return [4 /*yield*/, this.getCurrentVersion(lastRelease)];
762 case 11:
763 current = _a.sent();
764 if (semver_1.parse(current)) {
765 this.logger.log.warn("Published version would be: " + semver_1.inc(current, version));
766 }
767 _a.label = 12;
768 case 12: return [2 /*return*/, { newVersion: newVersion, commitsInRelease: commitsInRelease }];
769 }
770 });
771 });
772 };
773 Auto.prototype.getPrNumber = function (command, pr) {
774 var envPr = 'pr' in env && Number(env.pr);
775 var prNumber = pr || envPr;
776 if (!prNumber) {
777 throw new Error("Could not detect PR number. " + command + " must be run from either a PR or have the PR number supllied via the --pr flag.");
778 }
779 return prNumber;
780 };
781 Auto.prototype.startGit = function (gitOptions) {
782 if (!gitOptions.owner || !gitOptions.repo || !gitOptions.token) {
783 throw new Error('Must set owner, repo, and GitHub token.');
784 }
785 this.logger.verbose.info('Options contain repo information.');
786 // So that --verbose can be used on public CIs
787 var tokenlessArgs = __assign({}, gitOptions, { token: "[Token starting with " + gitOptions.token.substring(0, 4) + "]" });
788 this.logger.verbose.info('Initializing GitHub API with:\n', tokenlessArgs);
789 return new git_1.default({
790 owner: gitOptions.owner,
791 repo: gitOptions.repo,
792 token: gitOptions.token,
793 baseUrl: gitOptions.baseUrl,
794 graphqlBaseUrl: gitOptions.graphqlBaseUrl
795 }, this.logger);
796 };
797 Auto.prototype.getVersion = function () {
798 return __awaiter(this, void 0, void 0, function () {
799 var lastRelease;
800 return __generator(this, function (_a) {
801 switch (_a.label) {
802 case 0:
803 if (!this.git || !this.release) {
804 throw this.createErrorMessage();
805 }
806 return [4 /*yield*/, this.git.getLatestRelease()];
807 case 1:
808 lastRelease = _a.sent();
809 return [2 /*return*/, this.release.getSemverBump(lastRelease)];
810 }
811 });
812 });
813 };
814 Auto.prototype.makeChangelog = function (_a) {
815 var _b = _a === void 0 ? {} : _a, dryRun = _b.dryRun, from = _b.from, to = _b.to, message = _b.message;
816 return __awaiter(this, void 0, void 0, function () {
817 var lastRelease, _c, releaseNotes, currentVersion;
818 return __generator(this, function (_d) {
819 switch (_d.label) {
820 case 0:
821 if (!this.release || !this.git) {
822 throw this.createErrorMessage();
823 }
824 return [4 /*yield*/, this.setGitUser()];
825 case 1:
826 _d.sent();
827 _c = from;
828 if (_c) return [3 /*break*/, 3];
829 return [4 /*yield*/, this.git.getLatestRelease()];
830 case 2:
831 _c = (_d.sent());
832 _d.label = 3;
833 case 3:
834 lastRelease = _c;
835 return [4 /*yield*/, this.release.generateReleaseNotes(lastRelease, to || undefined)];
836 case 4:
837 releaseNotes = _d.sent();
838 this.logger.log.info('New Release Notes\n', releaseNotes);
839 if (dryRun) {
840 this.logger.verbose.info('`changelog` dry run complete.');
841 return [2 /*return*/];
842 }
843 return [4 /*yield*/, this.getCurrentVersion(lastRelease)];
844 case 5:
845 currentVersion = _d.sent();
846 return [4 /*yield*/, this.release.addToChangelog(releaseNotes, lastRelease, currentVersion, message)];
847 case 6:
848 _d.sent();
849 return [2 /*return*/];
850 }
851 });
852 });
853 };
854 Auto.prototype.makeRelease = function (_a) {
855 var _b = _a === void 0 ? {} : _a, dryRun = _b.dryRun, useVersion = _b.useVersion, slack = _b.slack;
856 return __awaiter(this, void 0, void 0, function () {
857 var lastRelease, commitsInRelease, releaseNotes, rawVersion, _c, _d, newVersion;
858 return __generator(this, function (_e) {
859 switch (_e.label) {
860 case 0:
861 if (!this.release || !this.git) {
862 throw this.createErrorMessage();
863 }
864 return [4 /*yield*/, this.git.getLatestRelease()];
865 case 1:
866 lastRelease = _e.sent();
867 // Find base commit or latest release to generate the changelog to HEAD (new tag)
868 this.logger.veryVerbose.info("Using " + lastRelease + " as previous release.");
869 if (lastRelease.match(/^\d+\.\d+\.\d+/)) {
870 lastRelease = this.prefixRelease(lastRelease);
871 }
872 this.logger.log.info('Last used release:', lastRelease);
873 return [4 /*yield*/, this.release.getCommitsInRelease(lastRelease)];
874 case 2:
875 commitsInRelease = _e.sent();
876 return [4 /*yield*/, this.release.generateReleaseNotes(lastRelease)];
877 case 3:
878 releaseNotes = _e.sent();
879 this.logger.log.info("Using release notes:\n" + releaseNotes);
880 _d = useVersion;
881 if (_d) return [3 /*break*/, 5];
882 return [4 /*yield*/, this.getCurrentVersion(lastRelease)];
883 case 4:
884 _d = (_e.sent());
885 _e.label = 5;
886 case 5:
887 _c = _d;
888 if (_c) return [3 /*break*/, 7];
889 return [4 /*yield*/, this.git.getLatestTagInBranch()];
890 case 6:
891 _c = (_e.sent());
892 _e.label = 7;
893 case 7:
894 rawVersion = _c;
895 if (!rawVersion) {
896 this.logger.log.error('Could not calculate next version from last tag.');
897 return [2 /*return*/];
898 }
899 newVersion = semver_1.parse(rawVersion)
900 ? this.prefixRelease(rawVersion)
901 : rawVersion;
902 if (!dryRun && semver_1.eq(newVersion, lastRelease)) {
903 this.logger.log.warn("Nothing released to Github. Version to be released is the same as the latest release on Github: " + newVersion);
904 return [2 /*return*/];
905 }
906 if (!!dryRun) return [3 /*break*/, 11];
907 this.logger.log.info("Releasing " + newVersion + " to GitHub.");
908 return [4 /*yield*/, this.git.publish(releaseNotes, newVersion)];
909 case 8:
910 _e.sent();
911 if (!(slack || (this.config && this.config.slack))) return [3 /*break*/, 10];
912 this.logger.log.info('Posting release to slack');
913 return [4 /*yield*/, this.release.postToSlack(releaseNotes, newVersion)];
914 case 9:
915 _e.sent();
916 _e.label = 10;
917 case 10: return [3 /*break*/, 12];
918 case 11:
919 this.logger.log.info("Would have released: " + newVersion);
920 _e.label = 12;
921 case 12: return [4 /*yield*/, this.hooks.afterRelease.promise(newVersion, commitsInRelease)];
922 case 13:
923 _e.sent();
924 return [2 /*return*/, newVersion];
925 }
926 });
927 });
928 };
929 Auto.prototype.createErrorMessage = function () {
930 return new Error("Auto is not initialized! Make sure the have run Auto.loadConfig");
931 };
932 /**
933 * Set the git user to make releases and commit with.
934 */
935 Auto.prototype.setGitUser = function () {
936 return __awaiter(this, void 0, void 0, function () {
937 var error_4, _a, email, name, packageAuthor;
938 return __generator(this, function (_b) {
939 switch (_b.label) {
940 case 0:
941 _b.trys.push([0, 3, , 9]);
942 // If these values are not set git config will exit with an error
943 return [4 /*yield*/, main_1.execPromise('git', ['config', 'user.email'])];
944 case 1:
945 // If these values are not set git config will exit with an error
946 _b.sent();
947 return [4 /*yield*/, main_1.execPromise('git', ['config', 'user.name'])];
948 case 2:
949 _b.sent();
950 return [3 /*break*/, 9];
951 case 3:
952 error_4 = _b.sent();
953 this.logger.verbose.warn('Could not find git user or email configured in environment');
954 if (!env.isCi) {
955 this.logger.log.note("Detected local environment, will not set git user. This happens automatically in a CI environment.\n\nIf a command fails manually run:\n\n - git config user.email your@email.com\n - git config user.name \"Your Name\"");
956 return [2 /*return*/];
957 }
958 if (!this.release) {
959 return [2 /*return*/];
960 }
961 _a = this.release.options, email = _a.email, name = _a.name;
962 this.logger.verbose.warn("Got author from options: email: " + email + ", name " + name);
963 return [4 /*yield*/, this.hooks.getAuthor.promise()];
964 case 4:
965 packageAuthor = _b.sent();
966 this.logger.verbose.warn("Got author: " + JSON.stringify(packageAuthor, undefined, 2));
967 email = packageAuthor ? packageAuthor.email : email;
968 name = packageAuthor ? packageAuthor.name : name;
969 if (!email) return [3 /*break*/, 6];
970 return [4 /*yield*/, main_1.execPromise('git', ['config', 'user.email', "\"" + email + "\""])];
971 case 5:
972 _b.sent();
973 this.logger.verbose.warn("Set git email to " + email);
974 _b.label = 6;
975 case 6:
976 if (!name) return [3 /*break*/, 8];
977 return [4 /*yield*/, main_1.execPromise('git', ['config', 'user.name', "\"" + name + "\""])];
978 case 7:
979 _b.sent();
980 this.logger.verbose.warn("Set git name to " + name);
981 _b.label = 8;
982 case 8: return [3 /*break*/, 9];
983 case 9: return [2 /*return*/];
984 }
985 });
986 });
987 };
988 Auto.prototype.getRepo = function (config) {
989 return __awaiter(this, void 0, void 0, function () {
990 return __generator(this, function (_a) {
991 if (config.owner && config.repo) {
992 return [2 /*return*/, config];
993 }
994 return [2 /*return*/, this.hooks.getRepository.promise()];
995 });
996 });
997 };
998 /**
999 * Apply all of the plugins in the config.
1000 */
1001 Auto.prototype.loadPlugins = function (config) {
1002 var _this = this;
1003 var pluginsPaths = config.plugins || ['npm'];
1004 pluginsPaths
1005 .map(function (plugin) {
1006 return typeof plugin === 'string' ? [plugin, {}] : plugin;
1007 })
1008 .map(function (plugin) { return load_plugins_1.default(plugin, _this.logger); })
1009 .filter(function (plugin) { return !!plugin; })
1010 .forEach(function (plugin) {
1011 _this.logger.verbose.info("Using " + plugin.name + " Plugin...");
1012 plugin.apply(_this);
1013 });
1014 };
1015 return Auto;
1016}());
1017exports.default = Auto;
1018//# sourceMappingURL=auto.js.map
\No newline at end of file