Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 25 additions & 46 deletions src/changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
unreleased,
Version,
} from './constants';
import { PackageRename } from './shared-types';

const changelogTitle = '# Changelog';
const changelogDescription = `All notable changes to this project will be documented in this file.
Expand Down Expand Up @@ -164,34 +165,29 @@ function getTagUrl(repoUrl: string, tag: string) {
* @param repoUrl - The URL for the GitHub repository.
* @param tagPrefix - The prefix used in tags before the version number.
* @param releases - The releases to generate link definitions for.
* @param versionBeforePackageRename - A version string of the package before being renamed.
* An optional, which is required only in case of package renamed.
* @param tagPrefixBeforePackageRename - A tag prefix string of the package before being renamed.
* @param packageRename - The package rename properties
* An optional, which is required only in case of package renamed.
* @returns The stringified release link definitions.
*/
function stringifyLinkReferenceDefinitions(
repoUrl: string,
tagPrefix: string,
releases: ReleaseMetadata[],
versionBeforePackageRename?: string,
tagPrefixBeforePackageRename?: string,
packageRename?: PackageRename,
) {
const unreleasedLinkReferenceDefinition =
getUnreleasedLinkReferenceDefinition(
repoUrl,
tagPrefix,
releases,
versionBeforePackageRename,
tagPrefixBeforePackageRename,
packageRename,
);

const releaseLinkReferenceDefinitions = getReleaseLinkReferenceDefinitions(
repoUrl,
tagPrefix,
releases,
versionBeforePackageRename,
tagPrefixBeforePackageRename,
packageRename,
).join('\n');
return `${unreleasedLinkReferenceDefinition}\n${releaseLinkReferenceDefinitions}${
releases.length > 0 ? '\n' : ''
Expand All @@ -204,16 +200,14 @@ function stringifyLinkReferenceDefinitions(
* @param repoUrl - The URL for the GitHub repository.
* @param tagPrefix - The prefix used in tags before the version number.
* @param releases - The releases to generate link definitions for.
* @param versionBeforePackageRename - A version string of the package before being renamed.
* @param tagPrefixBeforePackageRename - A tag prefix string of the package before being renamed.
* @param packageRename - The package rename properties.
* @returns A unreleased link reference definition string.
*/
function getUnreleasedLinkReferenceDefinition(
repoUrl: string,
tagPrefix: string,
releases: ReleaseMetadata[],
versionBeforePackageRename?: string,
tagPrefixBeforePackageRename?: string,
packageRename?: PackageRename,
): string {
// The "Unreleased" section represents all changes made since the *highest*
// release, not the most recent release. This is to accomodate patch releases
Expand All @@ -237,9 +231,8 @@ function getUnreleasedLinkReferenceDefinition(
// if there is a package renamed, the tag prefix before the rename will be considered for compare
// [Unreleased]: https://github.com/ExampleUsernameOrOrganization/ExampleRepository/compare/[email protected]
const tagPrefixToCompare =
tagPrefixBeforePackageRename &&
versionBeforePackageRename === latestSemverVersion
? tagPrefixBeforePackageRename
packageRename && packageRename.versionBeforeRename === latestSemverVersion
? packageRename.tagPrefixBeforeRename
: tagPrefix;

return `[${unreleased}]: ${
Expand All @@ -259,32 +252,26 @@ function getUnreleasedLinkReferenceDefinition(
* @param repoUrl - The URL for the GitHub repository.
* @param tagPrefix - The prefix used in tags before the version number.
* @param releases - The releases to generate link definitions for.
* @param versionBeforePackageRename - A version string of the package before being renamed.
* @param tagPrefixBeforePackageRename - A tag prefix string of the package before being renamed.
* @param packageRename - The package rename properties.
* @returns A list of release link reference definitions.
*/
function getReleaseLinkReferenceDefinitions(
repoUrl: string,
tagPrefix: string,
releases: ReleaseMetadata[],
versionBeforePackageRename?: string,
tagPrefixBeforePackageRename?: string,
packageRename?: PackageRename,
): string[] {
// The "previous" release that should be used for comparison is not always
// the most recent release chronologically. The _highest_ version that is
// lower than the current release is used as the previous release, so that
// patch releases on older releases can be accomodated.
// by default tag prefix from new package will be used
const chronologicalVersions = releases.map(({ version }) => version);
let tagPrefixToCompare = tagPrefix;
const releaseLinkReferenceDefinitions = releases.map(({ version }) => {
let diffUrl;
// once the version matches with versionBeforePackageRename, rest of the lines in changelog will be assumed as migrated tags
if (
tagPrefixBeforePackageRename &&
versionBeforePackageRename === version
) {
tagPrefixToCompare = tagPrefixBeforePackageRename;
// once the version matches with versionBeforeRename, rest of the lines in changelog will be assumed as migrated tags
if (packageRename && packageRename?.versionBeforeRename === version) {
tagPrefixToCompare = packageRename.tagPrefixBeforeRename;
}

if (version === chronologicalVersions[chronologicalVersions.length - 1]) {
Expand All @@ -299,14 +286,14 @@ function getReleaseLinkReferenceDefinitions(

if (previousVersion) {
if (
tagPrefixBeforePackageRename &&
versionBeforePackageRename === previousVersion
packageRename &&
packageRename.versionBeforeRename === previousVersion
) {
// The package was renamed at this version
// (the tag prefix holds the new name).
diffUrl = getCompareUrl(
repoUrl,
`${tagPrefixBeforePackageRename}${previousVersion}`,
`${packageRename.tagPrefixBeforeRename}${previousVersion}`,
`${tagPrefix}${version}`,
);
} else {
Expand Down Expand Up @@ -364,42 +351,35 @@ export default class Changelog {

#formatter: Formatter;

readonly #versionBeforePackageRename: string | undefined;

readonly #tagPrefixBeforePackageRename: string | undefined;
readonly #packageRename: PackageRename | undefined;

/**
* Construct an empty changelog.
*
* @param options - Changelog options.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
* @param options.formatter - A function that formats the changelog string.
* @param options.versionBeforePackageRename - A version string of the package before being renamed.
* An optional, which is required only in case of package renamed.
* @param options.tagPrefixBeforePackageRename - A tag prefix string of the package before being renamed.
* @param [options.tagPrefix] - The prefix used in tags before the version number.
* @param [options.formatter] - A function that formats the changelog string.
* @param [options.packageRename] - The package rename properties.
* An optional, which is required only in case of package renamed.
*/
constructor({
repoUrl,
tagPrefix = 'v',
formatter = (changelog) => changelog,
versionBeforePackageRename = undefined,
tagPrefixBeforePackageRename = undefined,
packageRename,
}: {
repoUrl: string;
tagPrefix?: string;
formatter?: Formatter;
versionBeforePackageRename?: string | undefined;
tagPrefixBeforePackageRename?: string | undefined;
packageRename?: PackageRename;
}) {
this.#releases = [];
this.#changes = { [unreleased]: {} };
this.#repoUrl = repoUrl;
this.#tagPrefix = tagPrefix;
this.#formatter = formatter;
this.#versionBeforePackageRename = versionBeforePackageRename;
this.#tagPrefixBeforePackageRename = tagPrefixBeforePackageRename;
this.#packageRename = packageRename;
}

/**
Expand Down Expand Up @@ -581,8 +561,7 @@ ${stringifyLinkReferenceDefinitions(
this.#repoUrl,
this.#tagPrefix,
this.#releases,
this.#versionBeforePackageRename,
this.#tagPrefixBeforePackageRename,
this.#packageRename,
)}`;

return this.#formatter(changelog);
Expand Down
38 changes: 23 additions & 15 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { unreleased, Version } from './constants';
import { generateDiff } from './generate-diff';
import { createEmptyChangelog } from './init';
import { getRepositoryUrl } from './repo';
import { PackageRename } from './shared-types';
import { updateChangelog } from './update-changelog';
import {
ChangelogFormattingError,
Expand Down Expand Up @@ -143,13 +144,9 @@ type ValidateOptions = {
fix: boolean;
formatter: Formatter;
/**
* Used in case of package renamed
* The package rename properties, used in case of package is renamed
*/
versionBeforePackageRename?: string;
/**
* Used in case of package renamed
*/
tagPrefixBeforePackageRename?: string;
packageRename?: PackageRename;
};

/**
Expand All @@ -163,9 +160,7 @@ type ValidateOptions = {
* @param options.tagPrefix - The prefix used in tags before the version number.
* @param options.fix - Whether to attempt to fix the changelog or not.
* @param options.formatter - A custom Markdown formatter to use.
* @param options.versionBeforePackageRename - A version of the package before being renamed.
* An optional, which is required only in case of package renamed.
* @param options.tagPrefixBeforePackageRename - A tag prefix of the package before being renamed.
* @param options.packageRename - The package rename properties.
* An optional, which is required only in case of package renamed.
*/
async function validate({
Expand All @@ -176,8 +171,7 @@ async function validate({
tagPrefix,
fix,
formatter,
versionBeforePackageRename,
tagPrefixBeforePackageRename,
packageRename,
}: ValidateOptions) {
const changelogContent = await readChangelog(changelogPath);

Expand All @@ -189,8 +183,7 @@ async function validate({
isReleaseCandidate,
tagPrefix,
formatter,
versionBeforePackageRename,
tagPrefixBeforePackageRename,
packageRename,
});
return undefined;
} catch (error) {
Expand Down Expand Up @@ -434,6 +427,15 @@ async function main() {
return exitWithError(`Invalid repo URL: '${repoUrl}'`);
}

if (
(versionBeforePackageRename && !tagPrefixBeforePackageRename) ||
(!versionBeforePackageRename && tagPrefixBeforePackageRename)
) {
return exitWithError(
'--version-before-package-rename and --tag-prefix-before-package-rename must be given together or not at all.',
);
}

let changelogPath = changelogFilename;
if (!path.isAbsolute(changelogFilename) && projectRootDirectory) {
changelogPath = path.resolve(projectRootDirectory, changelogFilename);
Expand Down Expand Up @@ -473,6 +475,13 @@ async function main() {
formatter,
});
} else if (command === 'validate') {
let packageRename: PackageRename | undefined;
if (versionBeforePackageRename && tagPrefixBeforePackageRename) {
packageRename = {
versionBeforeRename: versionBeforePackageRename,
tagPrefixBeforeRename: tagPrefixBeforePackageRename,
};
}
await validate({
changelogPath,
currentVersion,
Expand All @@ -481,8 +490,7 @@ async function main() {
tagPrefix,
fix,
formatter,
versionBeforePackageRename,
tagPrefixBeforePackageRename,
packageRename,
});
} else if (command === 'init') {
await init({
Expand Down
14 changes: 5 additions & 9 deletions src/parse-changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import semver from 'semver';

import Changelog, { Formatter } from './changelog';
import { ChangeCategory, unreleased } from './constants';
import { PackageRename } from './shared-types';

/**
* Truncate the given string at 80 characters.
Expand Down Expand Up @@ -32,9 +33,7 @@ function isValidChangeCategory(category: string): category is ChangeCategory {
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
* @param options.formatter - A custom Markdown formatter to use.
* @param options.versionBeforePackageRename - A version string of the package before being renamed.
* An optional, which is required only in case of package renamed.
* @param options.tagPrefixBeforePackageRename - A tag prefix string of the package before being renamed.
* @param options.packageRename - The package rename properties
* An optional, which is required only in case of package renamed.
* @returns A changelog instance that reflects the changelog text provided.
*/
Expand All @@ -43,23 +42,20 @@ export function parseChangelog({
repoUrl,
tagPrefix = 'v',
formatter = undefined,
versionBeforePackageRename = undefined,
tagPrefixBeforePackageRename = undefined,
packageRename,
}: {
changelogContent: string;
repoUrl: string;
tagPrefix?: string;
formatter?: Formatter;
versionBeforePackageRename?: string;
tagPrefixBeforePackageRename?: string;
packageRename?: PackageRename;
}) {
const changelogLines = changelogContent.split('\n');
const changelog = new Changelog({
repoUrl,
tagPrefix,
formatter,
versionBeforePackageRename,
tagPrefixBeforePackageRename,
packageRename,
});

const unreleasedHeaderIndex = changelogLines.indexOf(`## [${unreleased}]`);
Expand Down
13 changes: 13 additions & 0 deletions src/shared-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Package rename properties
*/
export type PackageRename = {
/**
* The version of the package before being renamed.
*/
versionBeforeRename: string;
/**
* The tag prefix of the package before being renamed.
*/
tagPrefixBeforeRename: string;
};
6 changes: 4 additions & 2 deletions src/validate-changelog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -723,8 +723,10 @@ describe('validateChangelog', () => {
'https://github.com/ExampleUsernameOrOrganization/ExampleRepository',
isReleaseCandidate: false,
tagPrefix: '@metamask/test@',
versionBeforePackageRename: '0.0.2',
tagPrefixBeforePackageRename: 'test@',
packageRename: {
versionBeforeRename: '0.0.2',
tagPrefixBeforeRename: 'test@',
},
}),
).not.toThrow();
});
Expand Down
Loading