UNPKG

47.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 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 (_a) {
427 var message = _a.message, pr = _a.pr, _b = _a.context, context = _b === void 0 ? 'default' : _b, dryRun = _a.dryRun;
428 return __awaiter(this, void 0, void 0, function () {
429 var prNumber;
430 return __generator(this, function (_c) {
431 switch (_c.label) {
432 case 0:
433 if (!this.git) {
434 throw this.createErrorMessage();
435 }
436 this.logger.verbose.info("Using command: 'comment'");
437 if (!dryRun) return [3 /*break*/, 1];
438 this.logger.log.info("Would have commented on " + pr + " under \"" + context + "\" context:\n\n" + message);
439 return [3 /*break*/, 3];
440 case 1:
441 prNumber = this.getPrNumber('comment', pr);
442 return [4 /*yield*/, this.git.createComment(message, prNumber, context)];
443 case 2:
444 _c.sent();
445 this.logger.log.success("Commented on PR #" + pr);
446 _c.label = 3;
447 case 3: return [2 /*return*/];
448 }
449 });
450 });
451 };
452 /**
453 * Update the body of a PR with a message. Only one message will be present in the PR,
454 * Older messages are removed. You can use the "context" option to multiple message
455 * in a PR body.
456 *
457 * @param options Options
458 */
459 Auto.prototype.prBody = function (_a) {
460 var message = _a.message, pr = _a.pr, _b = _a.context, context = _b === void 0 ? 'default' : _b, dryRun = _a.dryRun;
461 return __awaiter(this, void 0, void 0, function () {
462 var prNumber;
463 return __generator(this, function (_c) {
464 switch (_c.label) {
465 case 0:
466 if (!this.git) {
467 throw this.createErrorMessage();
468 }
469 this.logger.verbose.info("Using command: 'pr-body'");
470 if (!dryRun) return [3 /*break*/, 1];
471 this.logger.log.info("Would have appended to PR body on " + pr + " under \"" + context + "\" context:\n\n" + message);
472 return [3 /*break*/, 3];
473 case 1:
474 prNumber = this.getPrNumber('pr-body', pr);
475 return [4 /*yield*/, this.git.addToPrBody(message, prNumber, context)];
476 case 2:
477 _c.sent();
478 this.logger.log.success("Updated body on PR #" + prNumber);
479 _c.label = 3;
480 case 3: return [2 /*return*/];
481 }
482 });
483 });
484 };
485 /**
486 * Calculate the version bump for the current state of the repository.
487 */
488 Auto.prototype.version = function () {
489 return __awaiter(this, void 0, void 0, function () {
490 var bump;
491 return __generator(this, function (_a) {
492 switch (_a.label) {
493 case 0:
494 this.logger.verbose.info("Using command: 'version'");
495 return [4 /*yield*/, this.getVersion()];
496 case 1:
497 bump = _a.sent();
498 console.log(bump);
499 return [2 /*return*/];
500 }
501 });
502 });
503 };
504 /**
505 * Calculate the the changelog and commit it.
506 */
507 Auto.prototype.changelog = function (options) {
508 return __awaiter(this, void 0, void 0, function () {
509 return __generator(this, function (_a) {
510 switch (_a.label) {
511 case 0:
512 this.logger.verbose.info("Using command: 'changelog'");
513 return [4 /*yield*/, this.makeChangelog(options)];
514 case 1:
515 _a.sent();
516 return [2 /*return*/];
517 }
518 });
519 });
520 };
521 /**
522 * Make a release to the git remote with the changes.
523 */
524 Auto.prototype.runRelease = function (options) {
525 return __awaiter(this, void 0, void 0, function () {
526 return __generator(this, function (_a) {
527 switch (_a.label) {
528 case 0:
529 this.logger.verbose.info("Using command: 'release'");
530 return [4 /*yield*/, this.makeRelease(options)];
531 case 1:
532 _a.sent();
533 return [2 /*return*/];
534 }
535 });
536 });
537 };
538 Auto.prototype.canary = function (options) {
539 if (options === void 0) { options = {}; }
540 return __awaiter(this, void 0, void 0, function () {
541 var preId, build, head, labels, version, canaryVersion, _a, newVersion, result, message, latestTag, commitsInRelease;
542 return __generator(this, function (_b) {
543 switch (_b.label) {
544 case 0:
545 if (!this.git || !this.release) {
546 throw this.createErrorMessage();
547 }
548 if ('pr' in env && 'build' in env) {
549 preId = env.pr;
550 (build = env.build);
551 }
552 else if ('pr' in env && 'commit' in env) {
553 preId = env.pr;
554 build = env.commit;
555 }
556 preId = options.pr ? String(options.pr) : preId;
557 build = options.build ? String(options.build) : build;
558 return [4 /*yield*/, this.release.getCommitsInRelease('HEAD^')];
559 case 1:
560 head = _b.sent();
561 labels = head.map(function (commit) { return commit.labels; });
562 version = semver_2.calculateSemVerBump(labels, this.semVerLabels, this.config) ||
563 semver_2.default.patch;
564 canaryVersion = '';
565 if (preId) {
566 canaryVersion = canaryVersion + "." + preId;
567 }
568 if (build) {
569 canaryVersion = canaryVersion + "." + build;
570 }
571 if (!!('isPr' in env)) return [3 /*break*/, 3];
572 _a = canaryVersion + ".";
573 return [4 /*yield*/, this.git.getSha(true)];
574 case 2:
575 canaryVersion = _a + (_b.sent());
576 _b.label = 3;
577 case 3:
578 newVersion = '';
579 if (!options.dryRun) return [3 /*break*/, 4];
580 this.logger.log.warn("Published canary identifier would be: \"-canary" + canaryVersion + "\"");
581 return [3 /*break*/, 8];
582 case 4:
583 this.logger.verbose.info('Calling canary hook');
584 return [4 /*yield*/, this.hooks.canary.promise(version, canaryVersion)];
585 case 5:
586 result = _b.sent();
587 if (typeof result === 'object') {
588 this.logger.log.warn(result.error);
589 return [2 /*return*/];
590 }
591 newVersion = result;
592 message = options.message || 'Published PR with canary version: `%v`';
593 if (!(message !== 'false' && env.isCi)) return [3 /*break*/, 7];
594 return [4 /*yield*/, this.prBody({
595 message: message.replace('%v', newVersion),
596 context: 'canary-version'
597 })];
598 case 6:
599 _b.sent();
600 _b.label = 7;
601 case 7:
602 this.logger.log.success("Published canary version" + (newVersion ? ": " + newVersion : ''));
603 _b.label = 8;
604 case 8: return [4 /*yield*/, this.git.getLatestTagInBranch()];
605 case 9:
606 latestTag = _b.sent();
607 return [4 /*yield*/, this.release.getCommits(latestTag)];
608 case 10:
609 commitsInRelease = _b.sent();
610 return [2 /*return*/, { newVersion: newVersion, commitsInRelease: commitsInRelease }];
611 }
612 });
613 });
614 };
615 /**
616 * Run the full workflow.
617 *
618 * 1. Calculate version
619 * 2. Make changelog
620 * 3. Publish code
621 * 4. Create a release
622 */
623 Auto.prototype.shipit = function (options) {
624 if (options === void 0) { options = {}; }
625 return __awaiter(this, void 0, void 0, function () {
626 var isPR, isBaseBranch, publishInfo, _a, newVersion, commitsInRelease;
627 return __generator(this, function (_b) {
628 switch (_b.label) {
629 case 0:
630 if (!this.git || !this.release) {
631 throw this.createErrorMessage();
632 }
633 this.logger.verbose.info("Using command: 'shipit'");
634 this.hooks.beforeShipIt.call();
635 isPR = 'isPr' in env && env.isPr;
636 isBaseBranch = !isPR && 'branch' in env && env.branch === this.baseBranch;
637 if (!isBaseBranch) return [3 /*break*/, 2];
638 return [4 /*yield*/, this.publishLatest(options)];
639 case 1:
640 _a = _b.sent();
641 return [3 /*break*/, 4];
642 case 2: return [4 /*yield*/, this.canary(options)];
643 case 3:
644 _a = _b.sent();
645 _b.label = 4;
646 case 4:
647 publishInfo = _a;
648 if (!publishInfo) {
649 return [2 /*return*/];
650 }
651 newVersion = publishInfo.newVersion, commitsInRelease = publishInfo.commitsInRelease;
652 return [4 /*yield*/, this.hooks.afterShipIt.promise(newVersion, commitsInRelease)];
653 case 5:
654 _b.sent();
655 return [2 /*return*/];
656 }
657 });
658 });
659 };
660 Auto.prototype.getCurrentVersion = function (lastRelease) {
661 return __awaiter(this, void 0, void 0, function () {
662 var lastVersion;
663 var _this = this;
664 return __generator(this, function (_a) {
665 switch (_a.label) {
666 case 0:
667 this.hooks.getPreviousVersion.tap('None', function () {
668 _this.logger.veryVerbose.info('No previous release found, using 0.0.0 as previous version.');
669 return _this.prefixRelease('0.0.0');
670 });
671 return [4 /*yield*/, this.hooks.getPreviousVersion.promise(this.prefixRelease)];
672 case 1:
673 lastVersion = _a.sent();
674 if (semver_1.parse(lastRelease) &&
675 semver_1.parse(lastVersion) &&
676 semver_1.gt(lastRelease, lastVersion)) {
677 this.logger.veryVerbose.info('Using latest release as previous version');
678 return [2 /*return*/, lastRelease];
679 }
680 return [2 /*return*/, lastVersion];
681 }
682 });
683 });
684 };
685 Auto.prototype.publishLatest = function (options) {
686 return __awaiter(this, void 0, void 0, function () {
687 var version, lastRelease, commitsInRelease, newVersion, current;
688 return __generator(this, function (_a) {
689 switch (_a.label) {
690 case 0:
691 if (!this.git || !this.release) {
692 throw this.createErrorMessage();
693 }
694 return [4 /*yield*/, this.getVersion()];
695 case 1:
696 version = _a.sent();
697 if (version === '') {
698 this.logger.log.info('No version published.');
699 return [2 /*return*/];
700 }
701 return [4 /*yield*/, this.git.getLatestRelease()];
702 case 2:
703 lastRelease = _a.sent();
704 return [4 /*yield*/, this.release.getCommitsInRelease(lastRelease)];
705 case 3:
706 commitsInRelease = _a.sent();
707 return [4 /*yield*/, this.makeChangelog(options)];
708 case 4:
709 _a.sent();
710 if (!!options.dryRun) return [3 /*break*/, 9];
711 this.logger.verbose.info('Calling version hook');
712 return [4 /*yield*/, this.hooks.version.promise(version)];
713 case 5:
714 _a.sent();
715 this.logger.verbose.info('Calling after version hook');
716 return [4 /*yield*/, this.hooks.afterVersion.promise()];
717 case 6:
718 _a.sent();
719 this.logger.verbose.info('Calling publish hook');
720 return [4 /*yield*/, this.hooks.publish.promise(version)];
721 case 7:
722 _a.sent();
723 this.logger.verbose.info('Calling after publish hook');
724 return [4 /*yield*/, this.hooks.afterPublish.promise()];
725 case 8:
726 _a.sent();
727 _a.label = 9;
728 case 9: return [4 /*yield*/, this.makeRelease(options)];
729 case 10:
730 newVersion = _a.sent();
731 if (!options.dryRun) return [3 /*break*/, 12];
732 this.logger.log.warn("The version reported in the line above hasn't been incremented during `dry-run`");
733 return [4 /*yield*/, this.getCurrentVersion(lastRelease)];
734 case 11:
735 current = _a.sent();
736 if (semver_1.parse(current)) {
737 this.logger.log.warn("Published version would be: " + semver_1.inc(current, version));
738 }
739 _a.label = 12;
740 case 12: return [2 /*return*/, { newVersion: newVersion, commitsInRelease: commitsInRelease }];
741 }
742 });
743 });
744 };
745 Auto.prototype.getPrNumber = function (command, pr) {
746 var envPr = 'pr' in env && Number(env.pr);
747 var prNumber = pr || envPr;
748 if (!prNumber) {
749 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.");
750 }
751 return prNumber;
752 };
753 Auto.prototype.startGit = function (gitOptions) {
754 if (!gitOptions.owner || !gitOptions.repo || !gitOptions.token) {
755 throw new Error('Must set owner, repo, and GitHub token.');
756 }
757 this.logger.verbose.info('Options contain repo information.');
758 // So that --verbose can be used on public CIs
759 var tokenlessArgs = __assign({}, gitOptions, { token: "[Token starting with " + gitOptions.token.substring(0, 4) + "]" });
760 this.logger.verbose.info('Initializing GitHub API with:\n', tokenlessArgs);
761 return new git_1.default({
762 owner: gitOptions.owner,
763 repo: gitOptions.repo,
764 token: gitOptions.token,
765 baseUrl: gitOptions.baseUrl,
766 graphqlBaseUrl: gitOptions.graphqlBaseUrl
767 }, this.logger);
768 };
769 Auto.prototype.getVersion = function () {
770 return __awaiter(this, void 0, void 0, function () {
771 var lastRelease;
772 return __generator(this, function (_a) {
773 switch (_a.label) {
774 case 0:
775 if (!this.git || !this.release) {
776 throw this.createErrorMessage();
777 }
778 return [4 /*yield*/, this.git.getLatestRelease()];
779 case 1:
780 lastRelease = _a.sent();
781 return [2 /*return*/, this.release.getSemverBump(lastRelease)];
782 }
783 });
784 });
785 };
786 Auto.prototype.makeChangelog = function (_a) {
787 var _b = _a === void 0 ? {} : _a, dryRun = _b.dryRun, from = _b.from, to = _b.to, message = _b.message;
788 return __awaiter(this, void 0, void 0, function () {
789 var lastRelease, _c, releaseNotes, currentVersion;
790 return __generator(this, function (_d) {
791 switch (_d.label) {
792 case 0:
793 if (!this.release || !this.git) {
794 throw this.createErrorMessage();
795 }
796 return [4 /*yield*/, this.setGitUser()];
797 case 1:
798 _d.sent();
799 _c = from;
800 if (_c) return [3 /*break*/, 3];
801 return [4 /*yield*/, this.git.getLatestRelease()];
802 case 2:
803 _c = (_d.sent());
804 _d.label = 3;
805 case 3:
806 lastRelease = _c;
807 return [4 /*yield*/, this.release.generateReleaseNotes(lastRelease, to || undefined)];
808 case 4:
809 releaseNotes = _d.sent();
810 this.logger.log.info('New Release Notes\n', releaseNotes);
811 if (dryRun) {
812 this.logger.verbose.info('`changelog` dry run complete.');
813 return [2 /*return*/];
814 }
815 return [4 /*yield*/, this.getCurrentVersion(lastRelease)];
816 case 5:
817 currentVersion = _d.sent();
818 return [4 /*yield*/, this.release.addToChangelog(releaseNotes, lastRelease, currentVersion, message)];
819 case 6:
820 _d.sent();
821 return [2 /*return*/];
822 }
823 });
824 });
825 };
826 Auto.prototype.makeRelease = function (_a) {
827 var _b = _a === void 0 ? {} : _a, dryRun = _b.dryRun, useVersion = _b.useVersion, slack = _b.slack;
828 return __awaiter(this, void 0, void 0, function () {
829 var lastRelease, commitsInRelease, releaseNotes, rawVersion, _c, _d, version;
830 return __generator(this, function (_e) {
831 switch (_e.label) {
832 case 0:
833 if (!this.release || !this.git) {
834 throw this.createErrorMessage();
835 }
836 return [4 /*yield*/, this.git.getLatestRelease()];
837 case 1:
838 lastRelease = _e.sent();
839 // Find base commit or latest release to generate the changelog to HEAD (new tag)
840 this.logger.veryVerbose.info("Using " + lastRelease + " as previous release.");
841 if (lastRelease.match(/^\d+\.\d+\.\d+/)) {
842 lastRelease = this.prefixRelease(lastRelease);
843 }
844 this.logger.log.info('Last used release:', lastRelease);
845 return [4 /*yield*/, this.release.getCommitsInRelease(lastRelease)];
846 case 2:
847 commitsInRelease = _e.sent();
848 return [4 /*yield*/, this.release.generateReleaseNotes(lastRelease)];
849 case 3:
850 releaseNotes = _e.sent();
851 this.logger.log.info("Using release notes:\n" + releaseNotes);
852 _d = useVersion;
853 if (_d) return [3 /*break*/, 5];
854 return [4 /*yield*/, this.getCurrentVersion(lastRelease)];
855 case 4:
856 _d = (_e.sent());
857 _e.label = 5;
858 case 5:
859 _c = _d;
860 if (_c) return [3 /*break*/, 7];
861 return [4 /*yield*/, this.git.getLatestTagInBranch()];
862 case 6:
863 _c = (_e.sent());
864 _e.label = 7;
865 case 7:
866 rawVersion = _c;
867 if (!rawVersion) {
868 this.logger.log.error('Could not calculate next version from last tag.');
869 return [2 /*return*/];
870 }
871 version = semver_1.parse(rawVersion)
872 ? this.prefixRelease(rawVersion)
873 : rawVersion;
874 if (!!dryRun) return [3 /*break*/, 11];
875 this.logger.log.info("Releasing " + version + " to GitHub.");
876 return [4 /*yield*/, this.git.publish(releaseNotes, version)];
877 case 8:
878 _e.sent();
879 if (!(slack || (this.config && this.config.slack))) return [3 /*break*/, 10];
880 this.logger.log.info('Posting release to slack');
881 return [4 /*yield*/, this.release.postToSlack(releaseNotes, version)];
882 case 9:
883 _e.sent();
884 _e.label = 10;
885 case 10: return [3 /*break*/, 12];
886 case 11:
887 this.logger.log.info("Would have released: " + version);
888 _e.label = 12;
889 case 12: return [4 /*yield*/, this.hooks.afterRelease.promise(version, commitsInRelease)];
890 case 13:
891 _e.sent();
892 return [2 /*return*/, version];
893 }
894 });
895 });
896 };
897 Auto.prototype.createErrorMessage = function () {
898 return new Error("Auto is not initialized! Make sure the have run Auto.loadConfig");
899 };
900 /**
901 * Set the git user to make releases and commit with.
902 */
903 Auto.prototype.setGitUser = function () {
904 return __awaiter(this, void 0, void 0, function () {
905 var error_4, _a, email, name, packageAuthor;
906 return __generator(this, function (_b) {
907 switch (_b.label) {
908 case 0:
909 _b.trys.push([0, 3, , 9]);
910 // If these values are not set git config will exit with an error
911 return [4 /*yield*/, main_1.execPromise('git', ['config', 'user.email'])];
912 case 1:
913 // If these values are not set git config will exit with an error
914 _b.sent();
915 return [4 /*yield*/, main_1.execPromise('git', ['config', 'user.name'])];
916 case 2:
917 _b.sent();
918 return [3 /*break*/, 9];
919 case 3:
920 error_4 = _b.sent();
921 this.logger.verbose.warn('Could not find git user or email configured in environment');
922 if (!env.isCi) {
923 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\"");
924 return [2 /*return*/];
925 }
926 if (!this.release) {
927 return [2 /*return*/];
928 }
929 _a = this.release.options, email = _a.email, name = _a.name;
930 this.logger.verbose.warn("Got author from options: email: " + email + ", name " + name);
931 return [4 /*yield*/, this.hooks.getAuthor.promise()];
932 case 4:
933 packageAuthor = _b.sent();
934 this.logger.verbose.warn("Got author: " + JSON.stringify(packageAuthor, undefined, 2));
935 email = packageAuthor ? packageAuthor.email : email;
936 name = packageAuthor ? packageAuthor.name : name;
937 if (!email) return [3 /*break*/, 6];
938 return [4 /*yield*/, main_1.execPromise('git', ['config', 'user.email', "\"" + email + "\""])];
939 case 5:
940 _b.sent();
941 this.logger.verbose.warn("Set git email to " + email);
942 _b.label = 6;
943 case 6:
944 if (!name) return [3 /*break*/, 8];
945 return [4 /*yield*/, main_1.execPromise('git', ['config', 'user.name', "\"" + name + "\""])];
946 case 7:
947 _b.sent();
948 this.logger.verbose.warn("Set git name to " + name);
949 _b.label = 8;
950 case 8: return [3 /*break*/, 9];
951 case 9: return [2 /*return*/];
952 }
953 });
954 });
955 };
956 Auto.prototype.getRepo = function (config) {
957 return __awaiter(this, void 0, void 0, function () {
958 return __generator(this, function (_a) {
959 if (config.owner && config.repo) {
960 return [2 /*return*/, config];
961 }
962 return [2 /*return*/, this.hooks.getRepository.promise()];
963 });
964 });
965 };
966 /**
967 * Apply all of the plugins in the config.
968 */
969 Auto.prototype.loadPlugins = function (config) {
970 var _this = this;
971 var pluginsPaths = config.plugins || ['npm'];
972 pluginsPaths
973 .map(function (plugin) {
974 return typeof plugin === 'string' ? [plugin, {}] : plugin;
975 })
976 .map(function (plugin) { return load_plugins_1.default(plugin, _this.logger); })
977 .filter(function (plugin) { return !!plugin; })
978 .forEach(function (plugin) {
979 _this.logger.verbose.info("Using " + plugin.name + " Plugin...");
980 plugin.apply(_this);
981 });
982 };
983 return Auto;
984}());
985exports.default = Auto;
986//# sourceMappingURL=auto.js.map
\No newline at end of file