aboutsummaryrefslogtreecommitdiffstats
path: root/packages/monorepo-scripts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/monorepo-scripts')
-rw-r--r--packages/monorepo-scripts/CHANGELOG.md5
-rw-r--r--packages/monorepo-scripts/package.json12
-rw-r--r--packages/monorepo-scripts/src/globals.d.ts8
-rw-r--r--packages/monorepo-scripts/src/index.ts1
-rw-r--r--packages/monorepo-scripts/src/postpublish_utils.ts161
-rw-r--r--packages/monorepo-scripts/src/utils.ts5
6 files changed, 189 insertions, 3 deletions
diff --git a/packages/monorepo-scripts/CHANGELOG.md b/packages/monorepo-scripts/CHANGELOG.md
new file mode 100644
index 000000000..bb685a436
--- /dev/null
+++ b/packages/monorepo-scripts/CHANGELOG.md
@@ -0,0 +1,5 @@
+CHANGELOG
+
+## v0.1.13 - _TBD_
+
+ * Add postpublish utils
diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json
index 9a4e414e3..3a6fecf6a 100644
--- a/packages/monorepo-scripts/package.json
+++ b/packages/monorepo-scripts/package.json
@@ -1,8 +1,9 @@
{
"name": "@0xproject/monorepo-scripts",
"version": "0.1.12",
- "private": true,
"description": "Helper scripts for the monorepo",
+ "main": "lib/index.js",
+ "types": "lib/index.d.ts",
"scripts": {
"build:watch": "tsc -w",
"deps_versions": "node ./lib/deps_versions.js",
@@ -19,8 +20,9 @@
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/monorepo-scripts/README.md",
+ "comment": "// We purposefully use an older version of tslint-config here to avoid creating an import cycle",
"devDependencies": {
- "@0xproject/tslint-config": "^0.4.10",
+ "@0xproject/tslint-config": "0.4.8",
"@types/glob": "^5.0.33",
"@types/node": "^8.0.53",
"shx": "^0.2.2",
@@ -29,8 +31,12 @@
},
"dependencies": {
"@0xproject/utils": "^0.4.1",
+ "es6-promisify": "^5.0.0",
+ "async-child-process": "^1.1.1",
+ "publish-release": "0xproject/publish-release",
"chalk": "^2.3.0",
"glob": "^7.1.2",
- "lodash": "^4.17.4"
+ "lodash": "^4.17.4",
+ "semver-sort": "^0.0.4"
}
}
diff --git a/packages/monorepo-scripts/src/globals.d.ts b/packages/monorepo-scripts/src/globals.d.ts
new file mode 100644
index 000000000..757ae4097
--- /dev/null
+++ b/packages/monorepo-scripts/src/globals.d.ts
@@ -0,0 +1,8 @@
+declare module 'async-child-process';
+declare module 'publish-release';
+declare module 'es6-promisify';
+
+// semver-sort declarations
+declare module 'semver-sort' {
+ const desc: (versions: string[]) => string[];
+}
diff --git a/packages/monorepo-scripts/src/index.ts b/packages/monorepo-scripts/src/index.ts
new file mode 100644
index 000000000..95c96ebe8
--- /dev/null
+++ b/packages/monorepo-scripts/src/index.ts
@@ -0,0 +1 @@
+export { postpublishUtils } from './postpublish_utils';
diff --git a/packages/monorepo-scripts/src/postpublish_utils.ts b/packages/monorepo-scripts/src/postpublish_utils.ts
new file mode 100644
index 000000000..898b00c47
--- /dev/null
+++ b/packages/monorepo-scripts/src/postpublish_utils.ts
@@ -0,0 +1,161 @@
+import { execAsync } from 'async-child-process';
+import * as promisify from 'es6-promisify';
+import * as _ from 'lodash';
+import * as publishRelease from 'publish-release';
+import semverSort = require('semver-sort');
+
+import { utils } from './utils';
+
+const publishReleaseAsync = promisify(publishRelease);
+const githubPersonalAccessToken = process.env.GITHUB_PERSONAL_ACCESS_TOKEN_0X_JS;
+const generatedDocsDirectoryName = 'generated_docs';
+
+export interface PostpublishConfigs {
+ cwd: string;
+ packageName: string;
+ version: string;
+ assets: string[];
+ docPublishConfigs: DocPublishConfigs;
+}
+
+export interface DocPublishConfigs {
+ fileIncludes: string[];
+ s3BucketPath: string;
+ s3StagingBucketPath: string;
+}
+
+export const postpublishUtils = {
+ generateConfig(packageJSON: any, tsConfigJSON: any, cwd: string): PostpublishConfigs {
+ if (_.isUndefined(packageJSON.name)) {
+ throw new Error('name field required in package.json. Cannot publish release notes to Github.');
+ }
+ if (_.isUndefined(packageJSON.version)) {
+ throw new Error('version field required in package.json. Cannot publish release notes to Github.');
+ }
+ const postpublishConfig = _.get(packageJSON, 'config.postpublish', {});
+ const configs: PostpublishConfigs = {
+ cwd,
+ packageName: packageJSON.name,
+ version: packageJSON.version,
+ assets: _.get(postpublishConfig, 'assets', []),
+ docPublishConfigs: {
+ fileIncludes: [
+ ...tsConfigJSON.include,
+ ..._.get(postpublishConfig, 'docPublishConfigs.extraFileIncludes', []),
+ ],
+ s3BucketPath: _.get(postpublishConfig, 'docPublishConfigs.s3BucketPath'),
+ s3StagingBucketPath: _.get(postpublishConfig, 'docPublishConfigs.s3StagingBucketPath'),
+ },
+ };
+ return configs;
+ },
+ async runAsync(packageJSON: any, tsConfigJSON: any, cwd: string): Promise<void> {
+ const configs = this.generateConfig(packageJSON, tsConfigJSON, cwd);
+ const release = await this.publishReleaseNotesAsync(
+ configs.cwd,
+ configs.packageName,
+ configs.version,
+ configs.assets,
+ );
+ if (
+ !_.isUndefined(configs.docPublishConfigs.s3BucketPath) ||
+ !_.isUndefined(configs.docPublishConfigs.s3StagingBucketPath)
+ ) {
+ utils.log('POSTPUBLISH: Release successful, generating docs...');
+ await postpublishUtils.generateAndUploadDocsAsync(
+ configs.cwd,
+ configs.docPublishConfigs.fileIncludes,
+ configs.version,
+ configs.docPublishConfigs.s3BucketPath,
+ );
+ } else {
+ utils.log(`POSTPUBLISH: No S3Bucket config found for ${packageJSON.name}. Skipping doc JSON generation.`);
+ }
+ },
+ async publishDocsToStagingAsync(packageJSON: any, tsConfigJSON: any, cwd: string) {
+ const configs = this.generateConfig(packageJSON, tsConfigJSON, cwd);
+ if (_.isUndefined(configs.docPublishConfigs.s3StagingBucketPath)) {
+ utils.log('config.postpublish.docPublishConfigs.s3StagingBucketPath entry in package.json not found!');
+ return;
+ }
+
+ utils.log('POSTPUBLISH: Generating docs...');
+ await postpublishUtils.generateAndUploadDocsAsync(
+ configs.cwd,
+ configs.docPublishConfigs.fileIncludes,
+ configs.version,
+ configs.docPublishConfigs.s3StagingBucketPath,
+ );
+ },
+ async publishReleaseNotesAsync(cwd: string, packageName: string, version: string, assets: string[]): Promise<void> {
+ const releaseName = this.getReleaseName(packageName, version);
+ const tag = this.getTag(packageName, version);
+ utils.log('POSTPUBLISH: Releasing ', releaseName, '...');
+ const finalAssets = this.adjustAssetPaths(cwd, assets);
+ const result = await publishReleaseAsync({
+ token: githubPersonalAccessToken,
+ owner: '0xProject',
+ repo: '0x-monorepo',
+ tag,
+ name: releaseName,
+ notes: 'N/A',
+ draft: false,
+ prerelease: false,
+ reuseRelease: true,
+ reuseDraftOnly: false,
+ assets,
+ });
+ },
+ getTag(packageName: string, version: string) {
+ return `${packageName}@${version}`;
+ },
+ getReleaseName(subPackageName: string, version: string): string {
+ const releaseName = `${subPackageName} v${version}`;
+ return releaseName;
+ },
+ adjustAssetPaths(cwd: string, assets: string[]) {
+ const finalAssets: string[] = [];
+ _.each(assets, (asset: string) => {
+ finalAssets.push(`${cwd}/${asset}`);
+ });
+ return finalAssets;
+ },
+ adjustFileIncludePaths(fileIncludes: string[], cwd: string): string[] {
+ const fileIncludesAdjusted = _.map(fileIncludes, fileInclude => {
+ let path = _.startsWith(fileInclude, './') ? `${cwd}/${fileInclude.substr(2)}` : `${cwd}/${fileInclude}`;
+
+ // HACK: tsconfig.json needs wildcard directory endings as `/**/*`
+ // but TypeDoc needs it as `/**` in order to pick up files at the root
+ if (_.endsWith(path, '/**/*')) {
+ path = path.slice(0, -2);
+ }
+ return path;
+ });
+ return fileIncludesAdjusted;
+ },
+ async generateAndUploadDocsAsync(cwd: string, fileIncludes: string[], version: string, S3BucketPath: string) {
+ const fileIncludesAdjusted = this.adjustFileIncludePaths(fileIncludes, cwd);
+ const projectFiles = fileIncludesAdjusted.join(' ');
+ const jsonFilePath = `${cwd}/${generatedDocsDirectoryName}/index.json`;
+ const result = await execAsync(
+ `JSON_FILE_PATH=${jsonFilePath} PROJECT_FILES="${projectFiles}" yarn docs:json`,
+ {
+ cwd,
+ },
+ );
+ if (!_.isEmpty(result.stderr)) {
+ throw new Error(result.stderr);
+ }
+ const fileName = `v${version}.json`;
+ utils.log(`POSTPUBLISH: Doc generation successful, uploading docs... as ${fileName}`);
+ const s3Url = S3BucketPath + fileName;
+ await execAsync(`S3_URL=${s3Url} yarn upload_docs_json`, {
+ cwd,
+ });
+ // Remove the generated docs directory
+ await execAsync(`rm -rf ${generatedDocsDirectoryName}`, {
+ cwd,
+ });
+ utils.log(`POSTPUBLISH: Docs uploaded to S3 bucket: ${S3BucketPath}`);
+ },
+};
diff --git a/packages/monorepo-scripts/src/utils.ts b/packages/monorepo-scripts/src/utils.ts
new file mode 100644
index 000000000..5423cabd9
--- /dev/null
+++ b/packages/monorepo-scripts/src/utils.ts
@@ -0,0 +1,5 @@
+export const utils = {
+ log(...args: any[]): void {
+ console.log(...args); // tslint:disable-line:no-console
+ },
+};