Refactor changelog utils to a separate module

This commit is contained in:
Leonid Logvinov
2018-06-01 13:12:45 -07:00
parent 04a0eae241
commit 06e5fc233c
9 changed files with 78 additions and 63 deletions

View File

@@ -5,7 +5,7 @@ import * as fs from 'fs';
import { sync as globSync } from 'glob';
import * as _ from 'lodash';
import { utils } from './utils';
import { utils } from './utils/utils';
interface Dependencies {
[depName: string]: string;

View File

@@ -7,7 +7,7 @@ import * as _ from 'lodash';
import { exec as execAsync } from 'promisify-child-process';
import { constants } from './constants';
import { utils } from './utils';
import { utils } from './utils/utils';
// For some reason, `depcheck` hangs on some packages. Add them here.
const IGNORE_PACKAGES = ['@0xproject/sol-compiler'];

View File

@@ -7,7 +7,7 @@ import * as publishRelease from 'publish-release';
import semverSort = require('semver-sort');
import { constants } from './constants';
import { utils } from './utils';
import { utils } from './utils/utils';
const publishReleaseAsync = promisify(publishRelease);
const generatedDocsDirectoryName = 'generated_docs';

View File

@@ -13,14 +13,14 @@ import semverDiff = require('semver-diff');
import semverSort = require('semver-sort');
import { constants } from './constants';
import { Changelog, Changes, PackageToVersionChange, SemVerIndex, UpdatedPackage } from './types';
import { utils } from './utils';
import { Changelog, PackageToVersionChange, SemVerIndex, VersionChangelog } from './types';
import { changelogUtils } from './utils/changelog_utils';
import { utils } from './utils/utils';
const DOC_GEN_COMMAND = 'docs:json';
const NPM_NAMESPACE = '@0xproject/';
const IS_DRY_RUN = process.env.IS_DRY_RUN === 'true';
const TODAYS_TIMESTAMP = moment().unix();
const LERNA_EXECUTABLE = './node_modules/lerna/bin/lerna.js';
const semverNameToIndex: { [semver: string]: number } = {
patch: SemVerIndex.Patch,
minor: SemVerIndex.Minor,
@@ -118,7 +118,7 @@ async function checkPublishRequiredSetupAsync(): Promise<boolean> {
// check to see if logged into npm before publishing
try {
// HACK: for some reason on some setups, the `npm whoami` will not recognize a logged-in user
// unless run with `sudo` (i.e Fabio's NVM setup) but is fine for others (Jacob's N setup).
// unless run with `sudo` (i.e Fabio's NVM setup) but is fine for others (Jacob's NVM setup).
await execAsync(`sudo npm whoami`);
} catch (err) {
utils.log('You must be logged into npm in the commandline to publish. Run `npm login` and try again.');
@@ -175,7 +175,7 @@ async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[])
const packageName = lernaPackage.package.name;
const changelogJSONPath = path.join(lernaPackage.location, 'CHANGELOG.json');
const changelogJSON = utils.getChangelogJSONOrCreateIfMissing(changelogJSONPath);
let changelogs: Changelog[];
let changelogs: Changelog;
try {
changelogs = JSON.parse(changelogJSON);
} catch (err) {
@@ -185,11 +185,11 @@ async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[])
}
const currentVersion = lernaPackage.package.version;
const shouldAddNewEntry = shouldAddNewChangelogEntry(currentVersion, changelogs);
const shouldAddNewEntry = changelogUtils.shouldAddNewChangelogEntry(currentVersion, changelogs);
if (shouldAddNewEntry) {
// Create a new entry for a patch version with generic changelog entry.
const nextPatchVersion = utils.getNextPatchVersion(currentVersion);
const newChangelogEntry: Changelog = {
const newChangelogEntry: VersionChangelog = {
timestamp: TODAYS_TIMESTAMP,
version: nextPatchVersion,
changes: [
@@ -218,7 +218,7 @@ async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[])
await utils.prettifyAsync(changelogJSONPath, constants.monorepoRootPath);
utils.log(`${packageName}: Updated CHANGELOG.json`);
// Generate updated CHANGELOG.md
const changelogMd = generateChangelogMd(changelogs);
const changelogMd = changelogUtils.generateChangelogMd(changelogs);
const changelogMdPath = path.join(lernaPackage.location, 'CHANGELOG.md');
fs.writeFileSync(changelogMdPath, changelogMd);
await utils.prettifyAsync(changelogMdPath, constants.monorepoRootPath);
@@ -231,7 +231,8 @@ async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[])
async function lernaPublishAsync(packageToVersionChange: { [name: string]: string }): Promise<void> {
// HACK: Lerna publish does not provide a way to specify multiple package versions via
// flags so instead we need to interact with their interactive prompt interface.
const child = spawn('lerna', ['publish', '--registry=https://registry.npmjs.org/'], {
const PACKAGE_REGISTRY = 'https://registry.npmjs.org/';
const child = spawn('lerna', ['publish', `--registry=${PACKAGE_REGISTRY}`], {
cwd: constants.monorepoRootPath,
});
let shouldPrintOutput = false;
@@ -279,46 +280,3 @@ function updateVersionNumberIfNeeded(currentVersion: string, proposedNextVersion
}
return proposedNextVersion;
}
function shouldAddNewChangelogEntry(currentVersion: string, changelogs: Changelog[]): boolean {
if (_.isEmpty(changelogs)) {
return true;
}
const lastEntry = changelogs[0];
const isLastEntryCurrentVersion = lastEntry.version === currentVersion;
return isLastEntryCurrentVersion;
}
function generateChangelogMd(changelogs: Changelog[]): string {
let changelogMd = `<!--
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
`;
_.each(changelogs, changelog => {
if (_.isUndefined(changelog.timestamp)) {
throw new Error(
'All CHANGELOG.json entries must be updated to include a timestamp before generating their MD version',
);
}
const date = moment(`${changelog.timestamp}`, 'X').format('MMMM D, YYYY');
const title = `\n## v${changelog.version} - _${date}_\n\n`;
changelogMd += title;
let changes = '';
_.each(changelog.changes, change => {
let line = ` * ${change.note}`;
if (!_.isUndefined(change.pr)) {
line += ` (#${change.pr})`;
}
line += '\n';
changes += line;
});
changelogMd += `${changes}`;
});
return changelogMd;
}

View File

@@ -8,7 +8,7 @@ import semverSort = require('semver-sort');
import { constants } from './constants';
import { Changelog } from './types';
import { utils } from './utils';
import { utils } from './utils/utils';
(async () => {
const shouldIncludePrivate = true;
@@ -24,7 +24,7 @@ import { utils } from './utils';
let latestChangelogVersion: string;
if (!_.isUndefined(changelogJSONIfExists)) {
let changelogs: Changelog[];
let changelogs: Changelog;
try {
changelogs = JSON.parse(changelogJSONIfExists);
} catch (err) {

View File

@@ -7,7 +7,7 @@ import * as path from 'path';
import { exec as execAsync } from 'promisify-child-process';
import * as rimraf from 'rimraf';
import { utils } from './utils';
import { utils } from './utils/utils';
(async () => {
const monorepoRootPath = path.join(__dirname, '../../..');

View File

@@ -4,15 +4,17 @@ export interface UpdatedPackage {
private: boolean;
}
export interface Changes {
export interface Change {
note: string;
pr?: number;
}
export interface Changelog {
export type Changelog = VersionChangelog[];
export interface VersionChangelog {
timestamp?: number;
version: string;
changes: Changes[];
changes: Change[];
}
export enum SemVerIndex {

View File

@@ -0,0 +1,55 @@
import * as _ from 'lodash';
import * as moment from 'moment';
import { Change, Changelog, VersionChangelog } from '../types';
const CHANGELOG_MD_HEADER = `
<!--
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
`;
export const changelogUtils = {
getChangelogMdTitle(versionChangelog: VersionChangelog): string {
if (_.isUndefined(versionChangelog.timestamp)) {
throw new Error(
'All CHANGELOG.json entries must be updated to include a timestamp before generating their MD version',
);
}
const date = moment(`${versionChangelog.timestamp}`, 'X').format('MMMM D, YYYY');
const title = `\n## v${versionChangelog.version} - _${date}_\n\n`;
return title;
},
getChangelogMdChange(change: Change): string {
let line = ` * ${change.note}`;
if (!_.isUndefined(change.pr)) {
line += ` (#${change.pr})`;
}
return line;
},
generateChangelogMd(changelog: Changelog): string {
let changelogMd = CHANGELOG_MD_HEADER;
_.each(changelog, versionChangelog => {
const title = changelogUtils.getChangelogMdTitle(versionChangelog);
changelogMd += title;
const changelogVersionLines = _.map(
versionChangelog.changes,
changelogUtils.getChangelogMdChange.bind(changelogUtils),
);
changelogMd += `${_.join(changelogVersionLines, '\n')}`;
});
return changelogMd;
},
shouldAddNewChangelogEntry(currentVersion: string, changelog: Changelog): boolean {
if (_.isEmpty(changelog)) {
return true;
}
const lastEntry = changelog[0];
const isLastEntryCurrentVersion = lastEntry.version === currentVersion;
return isLastEntryCurrentVersion;
},
};

View File

@@ -3,8 +3,8 @@ import lernaGetPackages = require('lerna-get-packages');
import * as _ from 'lodash';
import { exec as execAsync, spawn } from 'promisify-child-process';
import { constants } from './constants';
import { UpdatedPackage } from './types';
import { constants } from '../constants';
import { UpdatedPackage } from '../types';
export const utils = {
log(...args: any[]): void {