aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package.json6
-rw-r--r--packages/contracts/src/utils/erc20_wrapper.ts48
-rw-r--r--packages/contracts/src/utils/erc721_wrapper.ts56
-rw-r--r--packages/contracts/src/utils/order_factory.ts3
-rw-r--r--packages/monorepo-scripts/CHANGELOG.json9
-rw-r--r--packages/monorepo-scripts/package.json1
-rw-r--r--packages/monorepo-scripts/src/deps_versions.ts2
-rw-r--r--packages/monorepo-scripts/src/find_unused_dependencies.ts2
-rw-r--r--packages/monorepo-scripts/src/postpublish_utils.ts2
-rw-r--r--packages/monorepo-scripts/src/prepublish_checks.ts71
-rw-r--r--packages/monorepo-scripts/src/publish.ts123
-rw-r--r--packages/monorepo-scripts/src/remove_tags.ts4
-rw-r--r--packages/monorepo-scripts/src/test_installation.ts2
-rw-r--r--packages/monorepo-scripts/src/types.ts8
-rw-r--r--packages/monorepo-scripts/src/utils/changelog_utils.ts55
-rw-r--r--packages/monorepo-scripts/src/utils/utils.ts (renamed from packages/monorepo-scripts/src/utils.ts)4
16 files changed, 219 insertions, 177 deletions
diff --git a/package.json b/package.json
index 177087f88..2ddde3484 100644
--- a/package.json
+++ b/package.json
@@ -13,8 +13,9 @@
"prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}' --config .prettierrc",
"report_coverage": "lcov-result-merger 'packages/*/coverage/lcov.info' | coveralls",
"test:installation": "node ./packages/monorepo-scripts/lib/test_installation.js",
- "run:publish": "run-s install:all rebuild script:publish",
- "run:publish:dry": "run-s install:all rebuild script:publish:dry",
+ "run:publish": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild script:publish",
+ "run:publish:dry": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild script:publish:dry",
+ "script:prepublish_checks": "node ./packages/monorepo-scripts/lib/prepublish_checks.js",
"script:publish": "node ./packages/monorepo-scripts/lib/publish.js",
"script:publish:dry": "IS_DRY_RUN=true yarn script:publish",
"install:all": "yarn install",
@@ -22,6 +23,7 @@
"lerna:run": "lerna run",
"watch": "wsrun watch $PKG --fast-exit -r --stages --done-criteria='complete|successfully'",
"build": "wsrun build $PKG --fast-exit -r --stages",
+ "build:monorepo_scripts": "PKG=@0xproject/monorepo-scripts yarn build",
"clean": "wsrun clean $PKG --fast-exit -r --parallel",
"rebuild": "run-s clean build",
"test": "wsrun test $PKG --fast-exit --serial --exclude-missing",
diff --git a/packages/contracts/src/utils/erc20_wrapper.ts b/packages/contracts/src/utils/erc20_wrapper.ts
index 0f45fb1e6..dceeceeea 100644
--- a/packages/contracts/src/utils/erc20_wrapper.ts
+++ b/packages/contracts/src/utils/erc20_wrapper.ts
@@ -16,18 +16,19 @@ export class ERC20Wrapper {
private _contractOwnerAddress: string;
private _web3Wrapper: Web3Wrapper;
private _provider: Provider;
- private _dummyTokenContracts?: DummyERC20TokenContract[];
+ private _dummyTokenContracts: DummyERC20TokenContract[];
private _proxyContract?: ERC20ProxyContract;
constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
+ this._dummyTokenContracts = [];
this._web3Wrapper = new Web3Wrapper(provider);
this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
}
public async deployDummyTokensAsync(): Promise<DummyERC20TokenContract[]> {
- this._dummyTokenContracts = await Promise.all(
- _.times(constants.NUM_DUMMY_ERC20_TO_DEPLOY, async () =>
- DummyERC20TokenContract.deployFrom0xArtifactAsync(
+ for (let i = 0; i < constants.NUM_DUMMY_ERC20_TO_DEPLOY; i++) {
+ this._dummyTokenContracts.push(
+ await DummyERC20TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC20Token,
this._provider,
txDefaults,
@@ -36,8 +37,8 @@ export class ERC20Wrapper {
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
- ),
- );
+ );
+ }
return this._dummyTokenContracts;
}
public async deployProxyAsync(): Promise<ERC20ProxyContract> {
@@ -51,44 +52,41 @@ export class ERC20Wrapper {
public async setBalancesAndAllowancesAsync(): Promise<void> {
this._validateDummyTokenContractsExistOrThrow();
this._validateProxyContractExistsOrThrow();
- const setBalancePromises: Array<Promise<string>> = [];
- const setAllowancePromises: Array<Promise<string>> = [];
- _.forEach(this._dummyTokenContracts, dummyTokenContract => {
- _.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
- setBalancePromises.push(
- dummyTokenContract.setBalance.sendTransactionAsync(
+ for (const dummyTokenContract of this._dummyTokenContracts) {
+ for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
+ await this._web3Wrapper.awaitTransactionSuccessAsync(
+ await dummyTokenContract.setBalance.sendTransactionAsync(
tokenOwnerAddress,
constants.INITIAL_ERC20_BALANCE,
{ from: this._contractOwnerAddress },
),
+ constants.AWAIT_TRANSACTION_MINED_MS,
);
- setAllowancePromises.push(
- dummyTokenContract.approve.sendTransactionAsync(
+ await this._web3Wrapper.awaitTransactionSuccessAsync(
+ await dummyTokenContract.approve.sendTransactionAsync(
(this._proxyContract as ERC20ProxyContract).address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: tokenOwnerAddress },
),
+ constants.AWAIT_TRANSACTION_MINED_MS,
);
- });
- });
- const txHashes = await Promise.all([...setBalancePromises, ...setAllowancePromises]);
- await Promise.all(_.map(txHashes, async txHash => this._web3Wrapper.awaitTransactionSuccessAsync(txHash)));
+ }
+ }
}
public async getBalancesAsync(): Promise<ERC20BalancesByOwner> {
this._validateDummyTokenContractsExistOrThrow();
const balancesByOwner: ERC20BalancesByOwner = {};
- const balancePromises: Array<Promise<BigNumber>> = [];
+ const balances: BigNumber[] = [];
const balanceInfo: Array<{ tokenOwnerAddress: string; tokenAddress: string }> = [];
- _.forEach(this._dummyTokenContracts, dummyTokenContract => {
- _.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
- balancePromises.push(dummyTokenContract.balanceOf.callAsync(tokenOwnerAddress));
+ for (const dummyTokenContract of this._dummyTokenContracts) {
+ for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
+ balances.push(await dummyTokenContract.balanceOf.callAsync(tokenOwnerAddress));
balanceInfo.push({
tokenOwnerAddress,
tokenAddress: dummyTokenContract.address,
});
- });
- });
- const balances = await Promise.all(balancePromises);
+ }
+ }
_.forEach(balances, (balance, balanceIndex) => {
const tokenAddress = balanceInfo[balanceIndex].tokenAddress;
const tokenOwnerAddress = balanceInfo[balanceIndex].tokenOwnerAddress;
diff --git a/packages/contracts/src/utils/erc721_wrapper.ts b/packages/contracts/src/utils/erc721_wrapper.ts
index 11a012602..13fdf630e 100644
--- a/packages/contracts/src/utils/erc721_wrapper.ts
+++ b/packages/contracts/src/utils/erc721_wrapper.ts
@@ -17,27 +17,28 @@ export class ERC721Wrapper {
private _contractOwnerAddress: string;
private _web3Wrapper: Web3Wrapper;
private _provider: Provider;
- private _dummyTokenContracts?: DummyERC721TokenContract[];
+ private _dummyTokenContracts: DummyERC721TokenContract[];
private _proxyContract?: ERC721ProxyContract;
private _initialTokenIdsByOwner: ERC721TokenIdsByOwner = {};
constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._web3Wrapper = new Web3Wrapper(provider);
this._provider = provider;
+ this._dummyTokenContracts = [];
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
}
public async deployDummyTokensAsync(): Promise<DummyERC721TokenContract[]> {
- this._dummyTokenContracts = await Promise.all(
- _.times(constants.NUM_DUMMY_ERC721_TO_DEPLOY, async () =>
- DummyERC721TokenContract.deployFrom0xArtifactAsync(
+ for (let i = 0; i < constants.NUM_DUMMY_ERC721_TO_DEPLOY; i++) {
+ this._dummyTokenContracts.push(
+ await DummyERC721TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC721Token,
this._provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
),
- ),
- );
+ );
+ }
return this._dummyTokenContracts;
}
public async deployProxyAsync(): Promise<ERC721ProxyContract> {
@@ -51,17 +52,16 @@ export class ERC721Wrapper {
public async setBalancesAndAllowancesAsync(): Promise<void> {
this._validateDummyTokenContractsExistOrThrow();
this._validateProxyContractExistsOrThrow();
- const setBalancePromises: Array<Promise<string>> = [];
- const setAllowancePromises: Array<Promise<string>> = [];
this._initialTokenIdsByOwner = {};
- _.forEach(this._dummyTokenContracts, dummyTokenContract => {
- _.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
- _.forEach(_.range(constants.NUM_ERC721_TOKENS_TO_MINT), () => {
+ for (const dummyTokenContract of this._dummyTokenContracts) {
+ for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
+ for (let i = 0; i < constants.NUM_ERC721_TOKENS_TO_MINT; i++) {
const tokenId = generatePseudoRandomSalt();
- setBalancePromises.push(
- dummyTokenContract.mint.sendTransactionAsync(tokenOwnerAddress, tokenId, {
+ await this._web3Wrapper.awaitTransactionSuccessAsync(
+ await dummyTokenContract.mint.sendTransactionAsync(tokenOwnerAddress, tokenId, {
from: this._contractOwnerAddress,
}),
+ constants.AWAIT_TRANSACTION_MINED_MS,
);
if (_.isUndefined(this._initialTokenIdsByOwner[tokenOwnerAddress])) {
this._initialTokenIdsByOwner[tokenOwnerAddress] = {
@@ -72,41 +72,39 @@ export class ERC721Wrapper {
this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address] = [];
}
this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address].push(tokenId);
- });
+ }
const shouldApprove = true;
- setAllowancePromises.push(
- dummyTokenContract.setApprovalForAll.sendTransactionAsync(
+ await this._web3Wrapper.awaitTransactionSuccessAsync(
+ await dummyTokenContract.setApprovalForAll.sendTransactionAsync(
(this._proxyContract as ERC721ProxyContract).address,
shouldApprove,
{ from: tokenOwnerAddress },
),
+ constants.AWAIT_TRANSACTION_MINED_MS,
);
- });
- });
- const txHashes = await Promise.all([...setBalancePromises, ...setAllowancePromises]);
- await Promise.all(_.map(txHashes, async txHash => this._web3Wrapper.awaitTransactionSuccessAsync(txHash)));
+ }
+ }
}
public async getBalancesAsync(): Promise<ERC721TokenIdsByOwner> {
this._validateDummyTokenContractsExistOrThrow();
this._validateBalancesAndAllowancesSetOrThrow();
const tokenIdsByOwner: ERC721TokenIdsByOwner = {};
- const tokenOwnerPromises: Array<Promise<string>> = [];
+ const tokenOwnerAddresses: string[] = [];
const tokenInfo: Array<{ tokenId: BigNumber; tokenAddress: string }> = [];
- _.forEach(this._dummyTokenContracts, dummyTokenContract => {
- _.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
+ for (const dummyTokenContract of this._dummyTokenContracts) {
+ for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
const initialTokenOwnerIds = this._initialTokenIdsByOwner[tokenOwnerAddress][
dummyTokenContract.address
];
- _.forEach(initialTokenOwnerIds, tokenId => {
- tokenOwnerPromises.push(dummyTokenContract.ownerOf.callAsync(tokenId));
+ for (const tokenId of initialTokenOwnerIds) {
+ tokenOwnerAddresses.push(await dummyTokenContract.ownerOf.callAsync(tokenId));
tokenInfo.push({
tokenId,
tokenAddress: dummyTokenContract.address,
});
- });
- });
- });
- const tokenOwnerAddresses = await Promise.all(tokenOwnerPromises);
+ }
+ }
+ }
_.forEach(tokenOwnerAddresses, (tokenOwnerAddress, ownerIndex) => {
const tokenAddress = tokenInfo[ownerIndex].tokenAddress;
const tokenId = tokenInfo[ownerIndex].tokenId;
diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts
index ef11e4341..af411c01f 100644
--- a/packages/contracts/src/utils/order_factory.ts
+++ b/packages/contracts/src/utils/order_factory.ts
@@ -17,7 +17,8 @@ export class OrderFactory {
customOrderParams: Partial<Order> = {},
signatureType: SignatureType = SignatureType.EthSign,
): SignedOrder {
- const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000));
+ const tenMinutes = 10 * 60 * 1000;
+ const randomExpiration = new BigNumber(Date.now() + tenMinutes);
const order = ({
senderAddress: constants.NULL_ADDRESS,
expirationTimeSeconds: randomExpiration,
diff --git a/packages/monorepo-scripts/CHANGELOG.json b/packages/monorepo-scripts/CHANGELOG.json
index 58d946cd6..a41262ed2 100644
--- a/packages/monorepo-scripts/CHANGELOG.json
+++ b/packages/monorepo-scripts/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "0.2.0",
+ "changes": [
+ {
+ "note": "Add `prepublish_checks` script",
+ "pr": 650
+ }
+ ]
+ },
+ {
"timestamp": 1527008794,
"version": "0.1.20",
"changes": [
diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json
index 02a8e4a42..2bbf4df11 100644
--- a/packages/monorepo-scripts/package.json
+++ b/packages/monorepo-scripts/package.json
@@ -16,6 +16,7 @@
"find_unused_deps": "run-s build script:find_unused_deps",
"remove_tags": "run-s build script:remove_tags",
"script:deps_versions": "node ./lib/deps_versions.js",
+ "script:prepublish_checks": "node ./lib/prepublish_checks.js",
"script:publish": "IS_DRY_RUN=true node ./lib/publish.js",
"script:find_unused_deps": "node ./lib/find_unused_dependencies.js",
"script:remove_tags": "node ./lib/remove_tags.js"
diff --git a/packages/monorepo-scripts/src/deps_versions.ts b/packages/monorepo-scripts/src/deps_versions.ts
index 07292a160..f090d12e9 100644
--- a/packages/monorepo-scripts/src/deps_versions.ts
+++ b/packages/monorepo-scripts/src/deps_versions.ts
@@ -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;
diff --git a/packages/monorepo-scripts/src/find_unused_dependencies.ts b/packages/monorepo-scripts/src/find_unused_dependencies.ts
index df303f6ce..71e707224 100644
--- a/packages/monorepo-scripts/src/find_unused_dependencies.ts
+++ b/packages/monorepo-scripts/src/find_unused_dependencies.ts
@@ -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'];
diff --git a/packages/monorepo-scripts/src/postpublish_utils.ts b/packages/monorepo-scripts/src/postpublish_utils.ts
index f5785343d..dbbde894d 100644
--- a/packages/monorepo-scripts/src/postpublish_utils.ts
+++ b/packages/monorepo-scripts/src/postpublish_utils.ts
@@ -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';
diff --git a/packages/monorepo-scripts/src/prepublish_checks.ts b/packages/monorepo-scripts/src/prepublish_checks.ts
new file mode 100644
index 000000000..2c096d8f6
--- /dev/null
+++ b/packages/monorepo-scripts/src/prepublish_checks.ts
@@ -0,0 +1,71 @@
+import * as _ from 'lodash';
+import { exec as execAsync } from 'promisify-child-process';
+
+import { constants } from './constants';
+import { utils } from './utils/utils';
+
+async function checkPublishRequiredSetupAsync(): Promise<void> {
+ // 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 NVM setup).
+ utils.log('Checking that the user is logged in on npm...');
+ await execAsync(`sudo npm whoami`);
+ } catch (err) {
+ throw new Error('You must be logged into npm in the commandline to publish. Run `npm login` and try again.');
+ }
+
+ // Check to see if Git personal token setup
+ if (_.isUndefined(constants.githubPersonalAccessToken)) {
+ throw new Error(
+ 'You must have a Github personal access token set to an envVar named `GITHUB_PERSONAL_ACCESS_TOKEN_0X_JS`. Add it then try again.',
+ );
+ }
+
+ // Check Yarn version is 1.X
+ utils.log('Checking the yarn version...');
+ const result = await execAsync(`yarn --version`);
+ const version = result.stdout;
+ const versionSegments = version.split('.');
+ const majorVersion = _.parseInt(versionSegments[0]);
+ if (majorVersion < 1) {
+ throw new Error('Your yarn version must be v1.x or higher. Upgrade yarn and try again.');
+ }
+
+ // Check that `aws` commandline tool is installed
+ try {
+ utils.log('Checking that aws CLI tool is installed...');
+ await execAsync(`aws help`);
+ } catch (err) {
+ throw new Error('You must have `awscli` commandline tool installed. Install it and try again.');
+ }
+
+ // Check that `aws` credentials are setup
+ try {
+ utils.log('Checking that aws credentials are configured...');
+ await execAsync(`aws sts get-caller-identity`);
+ } catch (err) {
+ throw new Error('You must setup your AWS credentials by running `aws configure`. Do this and try again.');
+ }
+
+ utils.log('Checking that git branch is up to date with upstream...');
+ await execAsync('git fetch');
+ const res = await execAsync('git status -bs'); // s - short format, b - branch info
+ /**
+ * Possible outcomes
+ * ## branch_name...origin/branch_name [behind n]
+ * ## branch_name...origin/branch_name [ahead n]
+ * ## branch_name...origin/branch_name
+ */
+ const gitShortStatusHeader = res.stdout.split('\n')[0];
+ if (gitShortStatusHeader.includes('behind')) {
+ throw new Error('Your branch is behind upstream. Please pull before publishing.');
+ } else if (gitShortStatusHeader.includes('ahead')) {
+ throw new Error('Your branch is ahead of upstream. Please push before publishing.');
+ }
+}
+
+checkPublishRequiredSetupAsync().catch(err => {
+ utils.log(err.message);
+ process.exit(1);
+});
diff --git a/packages/monorepo-scripts/src/publish.ts b/packages/monorepo-scripts/src/publish.ts
index 73106821a..36970f85b 100644
--- a/packages/monorepo-scripts/src/publish.ts
+++ b/packages/monorepo-scripts/src/publish.ts
@@ -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,
@@ -39,11 +39,6 @@ const packageNameToWebsitePath: { [name: string]: string } = {
};
(async () => {
- const hasRequiredSetup = await checkPublishRequiredSetupAsync();
- if (!hasRequiredSetup) {
- return; // abort
- }
-
// Fetch public, updated Lerna packages
const shouldIncludePrivate = false;
const updatedPublicLernaPackages = await utils.getUpdatedLernaPackagesAsync(shouldIncludePrivate);
@@ -114,54 +109,6 @@ package.ts. Please add an entry for it and try again.`,
}
}
-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).
- 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.');
- return false;
- }
-
- // Check to see if Git personal token setup
- if (_.isUndefined(constants.githubPersonalAccessToken)) {
- utils.log(
- 'You must have a Github personal access token set to an envVar named `GITHUB_PERSONAL_ACCESS_TOKEN_0X_JS`. Add it then try again.',
- );
- return false;
- }
-
- // Check Yarn version is 1.X
- const result = await execAsync(`yarn --version`);
- const version = result.stdout;
- const versionSegments = version.split('.');
- const majorVersion = _.parseInt(versionSegments[0]);
- if (majorVersion < 1) {
- utils.log('Your yarn version must be v1.x or higher. Upgrade yarn and try again.');
- return false;
- }
-
- // Check that `aws` commandline tool is installed
- try {
- await execAsync(`aws help`);
- } catch (err) {
- utils.log('You must have `awscli` commandline tool installed. Install it and try again.');
- return false;
- }
-
- // Check that `aws` credentials are setup
- try {
- await execAsync(`aws sts get-caller-identity`);
- } catch (err) {
- utils.log('You must setup your AWS credentials by running `aws configure`. Do this and try again.');
- return false;
- }
-
- return true;
-}
-
async function pushChangelogsToGithubAsync(): Promise<void> {
await execAsync(`git add . --all`, { cwd: constants.monorepoRootPath });
await execAsync(`git commit -m "Updated CHANGELOGS"`, { cwd: constants.monorepoRootPath });
@@ -175,9 +122,9 @@ 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 changelog: Changelog;
try {
- changelogs = JSON.parse(changelogJSON);
+ changelog = JSON.parse(changelogJSON);
} catch (err) {
throw new Error(
`${lernaPackage.package.name}'s CHANGELOG.json contains invalid JSON. Please fix and try again.`,
@@ -185,11 +132,11 @@ async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[])
}
const currentVersion = lernaPackage.package.version;
- const shouldAddNewEntry = shouldAddNewChangelogEntry(currentVersion, changelogs);
+ const shouldAddNewEntry = changelogUtils.shouldAddNewChangelogEntry(currentVersion, changelog);
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: [
@@ -198,27 +145,27 @@ async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[])
},
],
};
- changelogs = [newChangelogEntry, ...changelogs];
+ changelog = [newChangelogEntry, ...changelog];
packageToVersionChange[packageName] = semverDiff(currentVersion, nextPatchVersion);
} else {
// Update existing entry with timestamp
- const lastEntry = changelogs[0];
+ const lastEntry = changelog[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;
+ changelog[0] = lastEntry;
packageToVersionChange[packageName] = semverDiff(currentVersion, lastEntry.version);
}
// Save updated CHANGELOG.json
- fs.writeFileSync(changelogJSONPath, JSON.stringify(changelogs, null, '\t'));
+ fs.writeFileSync(changelogJSONPath, JSON.stringify(changelog, null, '\t'));
await utils.prettifyAsync(changelogJSONPath, constants.monorepoRootPath);
utils.log(`${packageName}: Updated CHANGELOG.json`);
// Generate updated CHANGELOG.md
- const changelogMd = generateChangelogMd(changelogs);
+ const changelogMd = changelogUtils.generateChangelogMd(changelog);
const changelogMdPath = path.join(lernaPackage.location, 'CHANGELOG.md');
fs.writeFileSync(changelogMdPath, changelogMd);
await utils.prettifyAsync(changelogMdPath, constants.monorepoRootPath);
@@ -231,7 +178,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 +227,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;
-}
diff --git a/packages/monorepo-scripts/src/remove_tags.ts b/packages/monorepo-scripts/src/remove_tags.ts
index 6d09729c7..affdf2751 100644
--- a/packages/monorepo-scripts/src/remove_tags.ts
+++ b/packages/monorepo-scripts/src/remove_tags.ts
@@ -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) {
diff --git a/packages/monorepo-scripts/src/test_installation.ts b/packages/monorepo-scripts/src/test_installation.ts
index e84221f9d..b67154667 100644
--- a/packages/monorepo-scripts/src/test_installation.ts
+++ b/packages/monorepo-scripts/src/test_installation.ts
@@ -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, '../../..');
diff --git a/packages/monorepo-scripts/src/types.ts b/packages/monorepo-scripts/src/types.ts
index 28d00d710..36fb923b3 100644
--- a/packages/monorepo-scripts/src/types.ts
+++ b/packages/monorepo-scripts/src/types.ts
@@ -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 {
diff --git a/packages/monorepo-scripts/src/utils/changelog_utils.ts b/packages/monorepo-scripts/src/utils/changelog_utils.ts
new file mode 100644
index 000000000..edfe65a80
--- /dev/null
+++ b/packages/monorepo-scripts/src/utils/changelog_utils.ts
@@ -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;
+ },
+};
diff --git a/packages/monorepo-scripts/src/utils.ts b/packages/monorepo-scripts/src/utils/utils.ts
index c2d92c86a..8f2a0bbaa 100644
--- a/packages/monorepo-scripts/src/utils.ts
+++ b/packages/monorepo-scripts/src/utils/utils.ts
@@ -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 {