UNPKG

4.72 kBJavaScriptView Raw
1'use strict';
2const inquirer = require('inquirer');
3const chalk = require('chalk');
4const githubUrlFromGit = require('github-url-from-git');
5const isScoped = require('is-scoped');
6const util = require('./util');
7const git = require('./git-util');
8const {prereleaseTags, checkIgnoreStrategy} = require('./npm/util');
9const version = require('./version');
10const prettyVersionDiff = require('./pretty-version-diff');
11
12const printCommitLog = async repoUrl => {
13 const latest = await git.latestTagOrFirstCommit();
14 const log = await git.commitLogFromRevision(latest);
15
16 if (!log) {
17 return {
18 hasCommits: false,
19 releaseNotes: () => {}
20 };
21 }
22
23 const commits = log.split('\n')
24 .map(commit => {
25 const splitIndex = commit.lastIndexOf(' ');
26 return {
27 message: commit.slice(0, splitIndex),
28 id: commit.slice(splitIndex + 1)
29 };
30 });
31
32 const history = commits.map(commit => {
33 const commitMessage = util.linkifyIssues(repoUrl, commit.message);
34 const commitId = util.linkifyCommit(repoUrl, commit.id);
35 return `- ${commitMessage} ${commitId}`;
36 }).join('\n');
37
38 const releaseNotes = nextTag => commits.map(commit =>
39 `- ${commit.message} ${commit.id}`
40 ).join('\n') + `\n\n${repoUrl}/compare/${latest}...${nextTag}`;
41
42 const commitRange = util.linkifyCommitRange(repoUrl, `${latest}...master`);
43
44 console.log(`${chalk.bold('Commits:')}\n${history}\n\n${chalk.bold('Commit Range:')}\n${commitRange}\n`);
45
46 return {
47 hasCommits: true,
48 releaseNotes
49 };
50};
51
52module.exports = async (options, pkg) => {
53 const oldVersion = pkg.version;
54 const extraBaseUrls = ['gitlab.com'];
55 const repoUrl = pkg.repository && githubUrlFromGit(pkg.repository.url, {extraBaseUrls});
56
57 checkIgnoreStrategy(pkg);
58
59 console.log(`\nPublish a new version of ${chalk.bold.magenta(pkg.name)} ${chalk.dim(`(current: ${oldVersion})`)}\n`);
60
61 const prompts = [
62 {
63 type: 'list',
64 name: 'version',
65 message: 'Select semver increment or specify new version',
66 pageSize: version.SEMVER_INCREMENTS.length + 2,
67 choices: version.SEMVER_INCREMENTS
68 .map(inc => ({
69 name: `${inc} ${prettyVersionDiff(oldVersion, inc)}`,
70 value: inc
71 }))
72 .concat([
73 new inquirer.Separator(),
74 {
75 name: 'Other (specify)',
76 value: null
77 }
78 ]),
79 filter: input => version.isValidInput(input) ? version(oldVersion).getNewVersionFrom(input) : input
80 },
81 {
82 type: 'input',
83 name: 'version',
84 message: 'Version',
85 when: answers => !answers.version,
86 filter: input => version.isValidInput(input) ? version(pkg.version).getNewVersionFrom(input) : input,
87 validate: input => {
88 if (!version.isValidInput(input)) {
89 return 'Please specify a valid semver, for example, `1.2.3`. See http://semver.org';
90 }
91
92 if (version(oldVersion).isLowerThanOrEqualTo(input)) {
93 return `Version must be greater than ${oldVersion}`;
94 }
95
96 return true;
97 }
98 },
99 {
100 type: 'list',
101 name: 'tag',
102 message: 'How should this pre-release version be tagged in npm?',
103 when: answers => !pkg.private && version.isPrereleaseOrIncrement(answers.version) && !options.tag,
104 choices: async () => {
105 const existingPrereleaseTags = await prereleaseTags(pkg.name);
106
107 return [
108 ...existingPrereleaseTags,
109 new inquirer.Separator(),
110 {
111 name: 'Other (specify)',
112 value: null
113 }
114 ];
115 }
116 },
117 {
118 type: 'input',
119 name: 'tag',
120 message: 'Tag',
121 when: answers => !pkg.private && version.isPrereleaseOrIncrement(answers.version) && !options.tag && !answers.tag,
122 validate: input => {
123 if (input.length === 0) {
124 return 'Please specify a tag, for example, `next`.';
125 }
126
127 if (input.toLowerCase() === 'latest') {
128 return 'It\'s not possible to publish pre-releases under the `latest` tag. Please specify something else, for example, `next`.';
129 }
130
131 return true;
132 }
133 },
134 {
135 type: 'confirm',
136 name: 'publishScoped',
137 when: isScoped(pkg.name) && !options.exists && options.publish && !pkg.private,
138 message: `This scoped repo ${chalk.bold.magenta(pkg.name)} hasn't been published. Do you want to publish it publicly?`,
139 default: false
140 }
141 ];
142
143 const {hasCommits, releaseNotes} = await printCommitLog(repoUrl);
144
145 if (options.version) {
146 return {
147 ...options,
148 confirm: true,
149 repoUrl,
150 releaseNotes
151 };
152 }
153
154 if (!hasCommits) {
155 const answers = await inquirer.prompt([{
156 type: 'confirm',
157 name: 'confirm',
158 message: 'No commits found since previous release, continue?',
159 default: false
160 }]);
161
162 if (!answers.confirm) {
163 return {
164 ...options,
165 ...answers
166 };
167 }
168 }
169
170 const answers = await inquirer.prompt(prompts);
171
172 return {
173 ...options,
174 ...answers,
175 confirm: true,
176 repoUrl,
177 releaseNotes
178 };
179};