Merge pull request #2786 from thelounge/xpaw/fix-changelog
Update changelog generator script
This commit is contained in:
commit
263d2ca133
@ -78,7 +78,11 @@ if (!version) {
|
|||||||
version = semver.inc(packageJson.version, process.argv[2]);
|
version = semver.inc(packageJson.version, process.argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!/^[0-9]+\.[0-9]+\.[0-9]+(-(pre|rc)+\.[0-9]+)?$/.test(version)) {
|
function isValidVersion(str) {
|
||||||
|
return (/^[0-9]+\.[0-9]+\.[0-9]+(-(pre|rc)+\.[0-9]+)?$/.test(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidVersion(version)) {
|
||||||
log.error(`Argument ${colors.bold("version")} is incorrect It must be either:`);
|
log.error(`Argument ${colors.bold("version")} is incorrect It must be either:`);
|
||||||
log.error(`- A keyword among: ${colors.green("major")}, ${colors.green("minor")}, ${colors.green("patch")}, ${colors.green("prerelease")}, ${colors.green("pre")}`);
|
log.error(`- A keyword among: ${colors.green("major")}, ${colors.green("minor")}, ${colors.green("patch")}, ${colors.green("prerelease")}, ${colors.green("pre")}`);
|
||||||
log.error(`- An explicit version of format ${colors.green("x.y.z")} (stable) or ${colors.green("x.y.z-(pre|rc).n")} (pre-release).`);
|
log.error(`- An explicit version of format ${colors.green("x.y.z")} (stable) or ${colors.green("x.y.z-(pre|rc).n")} (pre-release).`);
|
||||||
@ -151,7 +155,7 @@ ${printList(items.documentation)}`
|
|||||||
}
|
}
|
||||||
|
|
||||||
${_.isEmpty(items.websiteDocumentation) ? "" :
|
${_.isEmpty(items.websiteDocumentation) ? "" :
|
||||||
`On the [website repository](https://github.com/thelounge/thelounge.chat):
|
`On the [website repository](https://github.com/thelounge/thelounge.github.io):
|
||||||
|
|
||||||
${printList(items.websiteDocumentation)}`
|
${printList(items.websiteDocumentation)}`
|
||||||
}
|
}
|
||||||
@ -340,13 +344,25 @@ class RepositoryFetcher {
|
|||||||
return data.repository.milestones.nodes.find(({title}) => title === targetVersion);
|
return data.repository.milestones.nodes.find(({title}) => title === targetVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fetchChunkedPullRequests(numbers) {
|
||||||
|
const chunks = _.chunk(numbers, 100);
|
||||||
|
let result = {};
|
||||||
|
|
||||||
|
for (const chunk of chunks) {
|
||||||
|
const data = await this.fetchPullRequests(chunk);
|
||||||
|
result = _.merge(result, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Given a list of PR numbers, retrieve information for all those PRs. They
|
// Given a list of PR numbers, retrieve information for all those PRs. They
|
||||||
// are returned as a hash whose keys are `PR<number>`.
|
// are returned as a hash whose keys are `PR<number>`.
|
||||||
// This is a bit wonky (generating a dynamic GraphQL query) but the GitHub API
|
// This is a bit wonky (generating a dynamic GraphQL query) but the GitHub API
|
||||||
// does not have a way to retrieve multiple PRs given a list of IDs.
|
// does not have a way to retrieve multiple PRs given a list of IDs.
|
||||||
async fetchPullRequests(numbers) {
|
async fetchPullRequests(numbers) {
|
||||||
if (numbers.length === 0) {
|
if (numbers.length === 0) {
|
||||||
return [];
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const prQuery = `query fetchPullRequests($repositoryName: String!) {
|
const prQuery = `query fetchPullRequests($repositoryName: String!) {
|
||||||
@ -386,7 +402,7 @@ class RepositoryFetcher {
|
|||||||
const taggedCommit = await this.fetchTaggedCommit(tag);
|
const taggedCommit = await this.fetchTaggedCommit(tag);
|
||||||
const commits = await this.fetchCommitsSince(taggedCommit);
|
const commits = await this.fetchCommitsSince(taggedCommit);
|
||||||
const pullRequestIds = pullRequestNumbersInCommits(commits);
|
const pullRequestIds = pullRequestNumbersInCommits(commits);
|
||||||
const pullRequests = await this.fetchPullRequests(pullRequestIds);
|
const pullRequests = await this.fetchChunkedPullRequests(pullRequestIds);
|
||||||
return combine(commits, pullRequests);
|
return combine(commits, pullRequests);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -485,11 +501,12 @@ ${printList(items)}
|
|||||||
|
|
||||||
const dependencies = Object.keys(packageJson.dependencies);
|
const dependencies = Object.keys(packageJson.dependencies);
|
||||||
const devDependencies = Object.keys(packageJson.devDependencies);
|
const devDependencies = Object.keys(packageJson.devDependencies);
|
||||||
|
const optionalDependencies = Object.keys(packageJson.optionalDependencies);
|
||||||
|
|
||||||
// Returns the package.json section in which that package exists, or undefined
|
// Returns the package.json section in which that package exists, or undefined
|
||||||
// if that package is not listed there.
|
// if that package is not listed there.
|
||||||
function whichDependencyType(packageName) {
|
function whichDependencyType(packageName) {
|
||||||
if (dependencies.includes(packageName)) {
|
if (dependencies.includes(packageName) || optionalDependencies.includes(packageName)) {
|
||||||
return "dependencies";
|
return "dependencies";
|
||||||
} else if (devDependencies.includes(packageName)) {
|
} else if (devDependencies.includes(packageName)) {
|
||||||
return "devDependencies";
|
return "devDependencies";
|
||||||
@ -508,12 +525,20 @@ function hasLabel(labels, expected) {
|
|||||||
function hasAnnotatedComment(comments, expected) {
|
function hasAnnotatedComment(comments, expected) {
|
||||||
return comments && comments.nodes.some(({authorAssociation, body}) =>
|
return comments && comments.nodes.some(({authorAssociation, body}) =>
|
||||||
["OWNER", "MEMBER"].includes(authorAssociation) &&
|
["OWNER", "MEMBER"].includes(authorAssociation) &&
|
||||||
body.split("\n").includes(`[${expected}]`)
|
body.split("\r\n").includes(`[${expected}]`)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSkipped(entry) {
|
function isSkipped(entry) {
|
||||||
return hasLabelOrAnnotatedComment(entry, "Meta: Skip Changelog");
|
return (
|
||||||
|
(entry.messageHeadline && (
|
||||||
|
// Version bump commits created by `yarn version`
|
||||||
|
isValidVersion(entry.messageHeadline) ||
|
||||||
|
// Commit message suggested by this script
|
||||||
|
entry.messageHeadline.startsWith("Add changelog entry for v")
|
||||||
|
)) ||
|
||||||
|
hasLabelOrAnnotatedComment(entry, "Meta: Skip Changelog")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependency update PRs are listed in a special, more concise way in the changelog.
|
// Dependency update PRs are listed in a special, more concise way in the changelog.
|
||||||
@ -550,8 +575,20 @@ function isFeature({labels}) {
|
|||||||
// Update `stylelint` to v1.2.3
|
// Update `stylelint` to v1.2.3
|
||||||
// Update `express` and `ua-parser-js` to latest versions
|
// Update `express` and `ua-parser-js` to latest versions
|
||||||
// Update `express`, `chai`, and `ua-parser-js` to ...
|
// Update `express`, `chai`, and `ua-parser-js` to ...
|
||||||
function extractPackages(title) {
|
// Update @fortawesome/fontawesome-free-webfonts to the latest version
|
||||||
return /^Update ([\w-,`. ]+) to /.exec(title)[1]
|
// Update dependency request to v2.87.0
|
||||||
|
// chore(deps): update dependency mini-css-extract-plugin to v0.4.3
|
||||||
|
// fix(deps): update dependency web-push to v3.3.3
|
||||||
|
// chore(deps): update babel monorepo to v7.1.0
|
||||||
|
function extractPackages({title, url}) {
|
||||||
|
const extracted = /(?:U|u)pdate(?: dependency)? ([\w-,` ./@]+?) (?:monorepo )?to /.exec(title);
|
||||||
|
|
||||||
|
if (!extracted) {
|
||||||
|
log.warn(`Failed to extract package from: ${title} ${colors.gray(url)}`);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return extracted[1]
|
||||||
.replace(/`/g, "")
|
.replace(/`/g, "")
|
||||||
.split(/, and |, | and /);
|
.split(/, and |, | and /);
|
||||||
}
|
}
|
||||||
@ -560,10 +597,12 @@ function extractPackages(title) {
|
|||||||
// based on different information that describes them.
|
// based on different information that describes them.
|
||||||
function parse(entries) {
|
function parse(entries) {
|
||||||
return entries.reduce((result, entry) => {
|
return entries.reduce((result, entry) => {
|
||||||
|
let deps;
|
||||||
|
|
||||||
if (isSkipped(entry)) {
|
if (isSkipped(entry)) {
|
||||||
result.skipped.push(entry);
|
result.skipped.push(entry);
|
||||||
} else if (isDependency(entry)) {
|
} else if (isDependency(entry) && (deps = extractPackages(entry))) {
|
||||||
extractPackages(entry.title).forEach((packageName) => {
|
deps.forEach((packageName) => {
|
||||||
const dependencyType = whichDependencyType(packageName);
|
const dependencyType = whichDependencyType(packageName);
|
||||||
|
|
||||||
if (dependencyType) {
|
if (dependencyType) {
|
||||||
@ -573,7 +612,7 @@ function parse(entries) {
|
|||||||
|
|
||||||
result[dependencyType][packageName].push(entry);
|
result[dependencyType][packageName].push(entry);
|
||||||
} else {
|
} else {
|
||||||
log.info(`${colors.bold(packageName)} was updated in ${colors.green("#" + entry.number)} then removed since last release. Skipping.`);
|
log.info(`${colors.bold(packageName)} was updated in ${colors.green("#" + entry.number)} then removed since last release. Skipping. ${colors.gray(entry.url)}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (isDocumentation(entry)) {
|
} else if (isDocumentation(entry)) {
|
||||||
@ -654,8 +693,9 @@ async function generateChangelogEntry(targetVersion) {
|
|||||||
items.milestone = await codeRepo.fetchMilestone(targetVersion);
|
items.milestone = await codeRepo.fetchMilestone(targetVersion);
|
||||||
contributors = extractContributors(codeCommitsAndPullRequests);
|
contributors = extractContributors(codeCommitsAndPullRequests);
|
||||||
|
|
||||||
const websiteRepo = new RepositoryFetcher(client, "thelounge.chat");
|
const websiteRepo = new RepositoryFetcher(client, "thelounge.github.io");
|
||||||
items.websiteDocumentation = await websiteRepo.fetchCommitsAndPullRequestsSince("v" + previousVersion);
|
const previousWebsiteVersion = await websiteRepo.fetchPreviousVersion(targetVersion);
|
||||||
|
items.websiteDocumentation = await websiteRepo.fetchCommitsAndPullRequestsSince("v" + previousWebsiteVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
items.version = targetVersion;
|
items.version = targetVersion;
|
||||||
|
Loading…
Reference in New Issue
Block a user