UNPKG

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