aboutsummaryrefslogtreecommitdiffstats
path: root/packages/monorepo-scripts/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/monorepo-scripts/src')
-rw-r--r--packages/monorepo-scripts/src/custom_prepublish.ts117
-rw-r--r--packages/monorepo-scripts/src/globals.d.ts1
2 files changed, 118 insertions, 0 deletions
diff --git a/packages/monorepo-scripts/src/custom_prepublish.ts b/packages/monorepo-scripts/src/custom_prepublish.ts
new file mode 100644
index 000000000..7f0e186bd
--- /dev/null
+++ b/packages/monorepo-scripts/src/custom_prepublish.ts
@@ -0,0 +1,117 @@
+#!/usr/bin/env node
+
+import * as fs from 'fs';
+import lernaGetPackages = require('lerna-get-packages');
+import * as _ from 'lodash';
+import * as moment from 'moment';
+import * as path from 'path';
+import { exec as execAsync } from 'promisify-child-process';
+import semverSort = require('semver-sort');
+
+import { Changelog, Changes, UpdatedPackage } from './types';
+import { utils } from './utils';
+
+const MONOREPO_ROOT_PATH = path.join(__dirname, '../../..');
+const TODAYS_TIMESTAMP = moment().unix();
+
+(async () => {
+ const updatedPublicPackages = await getPublicLernaUpdatedPackagesAsync();
+ const updatedPackageNames = _.map(updatedPublicPackages, pkg => pkg.name);
+
+ const allLernaPackages = lernaGetPackages(MONOREPO_ROOT_PATH);
+ const relevantLernaPackages = _.filter(allLernaPackages, pkg => {
+ return _.includes(updatedPackageNames, pkg.package.name);
+ });
+ _.each(relevantLernaPackages, lernaPackage => {
+ const changelogJSONPath = path.join(lernaPackage.location, 'CHANGELOG.json');
+ const changelogJSON = getChangelogJSONOrCreateIfMissing(lernaPackage.package.name, changelogJSONPath);
+ let changelogs: Changelog[];
+ try {
+ changelogs = JSON.parse(changelogJSON);
+ } catch (err) {
+ throw new Error(
+ `${lernaPackage.package.name}'s CHANGELOG.json contains invalid JSON. Please fix and try again.`,
+ );
+ }
+
+ const currentVersion = lernaPackage.package.version;
+ const shouldAddNewEntry = shouldAddNewChangelogEntry(changelogs);
+ if (shouldAddNewEntry) {
+ // Create a new entry for a patch version with generic changelog entry.
+ const nextPatchVersion = utils.getNextPatchVersion(currentVersion);
+ const newChangelogEntry: Changelog = {
+ timestamp: TODAYS_TIMESTAMP,
+ version: nextPatchVersion,
+ changes: [
+ {
+ note: 'Dependencies updated',
+ },
+ ],
+ };
+ changelogs = [newChangelogEntry, ...changelogs];
+ } else {
+ // Update existing entry with timestamp
+ const lastEntry = changelogs[0];
+ if (_.isUndefined(lastEntry.timestamp)) {
+ lastEntry.timestamp = TODAYS_TIMESTAMP;
+ }
+ // Check version number is correct.
+ const proposedNextVersion = lastEntry.version;
+ lastEntry.version = updateVersionNumberIfNeeded(currentVersion, proposedNextVersion);
+ changelogs[0] = lastEntry;
+ }
+
+ // Save updated CHANGELOG.json
+ fs.writeFileSync(changelogJSONPath, JSON.stringify(changelogs, null, '\t'));
+ // Generate updated CHANGELOG.md
+ const changelogMd = generateChangelogMd(changelogs);
+ });
+})().catch(err => {
+ utils.log(err);
+ process.exit(1);
+});
+
+async function getPublicLernaUpdatedPackagesAsync(): Promise<UpdatedPackage[]> {
+ const result = await execAsync(`./node_modules/lerna/bin/lerna.js updated --json`, { cwd: MONOREPO_ROOT_PATH });
+ const updatedPackages = JSON.parse(result.stdout);
+ const updatedPublicPackages = _.filter(updatedPackages, updatedPackage => !updatedPackage.private);
+ return updatedPublicPackages;
+}
+
+function updateVersionNumberIfNeeded(currentVersion: string, proposedNextVersion: string) {
+ console.log('currentVersion', currentVersion);
+ console.log('proposedNextVersion', proposedNextVersion);
+ if (proposedNextVersion === currentVersion) {
+ return utils.getNextPatchVersion(currentVersion);
+ }
+ const sortedVersions = semverSort.desc([proposedNextVersion, currentVersion]);
+ if (sortedVersions[0] !== proposedNextVersion) {
+ return utils.getNextPatchVersion(currentVersion);
+ }
+ return proposedNextVersion;
+}
+
+function getChangelogJSONOrCreateIfMissing(packageName: string, changelogPath: string): string {
+ let changelogJSON: string;
+ try {
+ changelogJSON = fs.readFileSync(changelogPath, 'utf-8');
+ return changelogJSON;
+ } catch (err) {
+ // If none exists, create new, empty one.
+ const emptyChangelogJSON = JSON.stringify([]);
+ fs.writeFileSync(changelogPath, emptyChangelogJSON);
+ return emptyChangelogJSON;
+ }
+}
+
+function shouldAddNewChangelogEntry(changelogs: Changelog[]): boolean {
+ if (_.isEmpty(changelogs)) {
+ return true;
+ }
+ const lastEntry = changelogs[0];
+ return !!lastEntry.isPublished;
+}
+
+function generateChangelogMd(changelogs: Changelog[]): string {
+ return '';
+}
diff --git a/packages/monorepo-scripts/src/globals.d.ts b/packages/monorepo-scripts/src/globals.d.ts
index 1d49559f2..90adc0b78 100644
--- a/packages/monorepo-scripts/src/globals.d.ts
+++ b/packages/monorepo-scripts/src/globals.d.ts
@@ -11,6 +11,7 @@ declare interface LernaPackage {
location: string;
package: {
private?: boolean;
+ version: string;
name: string;
main?: string;
config?: {