aboutsummaryrefslogtreecommitdiffstats
path: root/packages/monorepo-scripts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/monorepo-scripts')
-rw-r--r--packages/monorepo-scripts/src/prepublish_checks.ts8
-rw-r--r--packages/monorepo-scripts/src/publish.ts45
-rw-r--r--packages/monorepo-scripts/src/types.ts6
-rw-r--r--packages/monorepo-scripts/src/utils/configs.ts1
-rw-r--r--packages/monorepo-scripts/src/utils/docker_hub_utils.ts65
5 files changed, 121 insertions, 4 deletions
diff --git a/packages/monorepo-scripts/src/prepublish_checks.ts b/packages/monorepo-scripts/src/prepublish_checks.ts
index 82eaf5cf9..021e57226 100644
--- a/packages/monorepo-scripts/src/prepublish_checks.ts
+++ b/packages/monorepo-scripts/src/prepublish_checks.ts
@@ -6,6 +6,8 @@ import semverSort = require('semver-sort');
import { constants } from './constants';
import { Package } from './types';
import { changelogUtils } from './utils/changelog_utils';
+import { configs } from './utils/configs';
+import { dockerHubUtils } from './utils/docker_hub_utils';
import { npmUtils } from './utils/npm_utils';
import { utils } from './utils/utils';
@@ -17,6 +19,12 @@ async function prepublishChecksAsync(): Promise<void> {
await checkChangelogFormatAsync(updatedPublicPackages);
await checkGitTagsForNextVersionAndDeleteIfExistAsync(updatedPublicPackages);
await checkPublishRequiredSetupAsync();
+ await checkDockerHubSetupAsync();
+}
+
+async function checkDockerHubSetupAsync(): Promise<void> {
+ await dockerHubUtils.checkUserAddedToOrganizationOrThrowAsync(configs.DOCKER_HUB_ORG);
+ await dockerHubUtils.loginUserToDockerCommandlineOrThrowAsync();
}
async function checkGitTagsForNextVersionAndDeleteIfExistAsync(updatedPublicPackages: Package[]): Promise<void> {
diff --git a/packages/monorepo-scripts/src/publish.ts b/packages/monorepo-scripts/src/publish.ts
index e0602a74f..105d87dcd 100644
--- a/packages/monorepo-scripts/src/publish.ts
+++ b/packages/monorepo-scripts/src/publish.ts
@@ -1,11 +1,12 @@
#!/usr/bin/env node
+import { logUtils } from '@0x/utils';
import * as promisify from 'es6-promisify';
import * as fs from 'fs';
import * as _ from 'lodash';
import * as moment from 'moment';
import opn = require('opn');
-import { exec as execAsync } from 'promisify-child-process';
+import { exec as execAsync, spawn as spawnAsync } from 'promisify-child-process';
import * as prompt from 'prompt';
import semver = require('semver');
import semverSort = require('semver-sort');
@@ -79,12 +80,16 @@ async function confirmAsync(message: string): Promise<void> {
});
utils.log(`Calling 'lerna publish'...`);
await lernaPublishAsync(packageToNextVersion);
- if (!configs.IS_LOCAL_PUBLISH) {
+
+ const isDryRun = configs.IS_LOCAL_PUBLISH;
+ if (!isDryRun) {
+ // Publish docker images to DockerHub
+ await publishImagesToDockerHubAsync(allPackagesToPublish);
+
const isStaging = false;
const shouldUploadDocs = true;
await generateAndUploadDocJsonsAsync(packagesWithDocs, isStaging, shouldUploadDocs);
}
- const isDryRun = configs.IS_LOCAL_PUBLISH;
const releaseNotes = await publishReleaseNotesAsync(updatedPublicPackages, isDryRun);
utils.log('Published release notes');
@@ -95,11 +100,45 @@ async function confirmAsync(message: string): Promise<void> {
utils.log("Publish successful, but couldn't auto-alert discord (", e.message, '), Please alert manually.');
}
}
+ process.exit(0);
})().catch(err => {
utils.log(err);
process.exit(1);
});
+async function publishImagesToDockerHubAsync(allUpdatedPackages: Package[]): Promise<void> {
+ for (const pkg of allUpdatedPackages) {
+ const packageJSON = pkg.packageJson;
+ const shouldPublishDockerImage =
+ !_.isUndefined(packageJSON.config) &&
+ !_.isUndefined(packageJSON.config.postpublish) &&
+ !_.isUndefined(packageJSON.config.postpublish.dockerHubRepo);
+ if (!shouldPublishDockerImage) {
+ continue;
+ }
+ const dockerHubRepo = _.get(packageJSON, 'config.postpublish.dockerHubRepo');
+ const pkgName = pkg.packageJson.name;
+ const packageDirName = _.startsWith(pkgName, '@0x/') ? pkgName.split('/')[1] : pkgName;
+
+ // Build the Docker image
+ logUtils.log(`Building '${dockerHubRepo}' docker image...`);
+ await spawnAsync('docker', ['build', '-t', dockerHubRepo, '.'], {
+ cwd: `${constants.monorepoRootPath}/packages/${packageDirName}`,
+ });
+
+ // Tag the docker image with the latest version
+ const version = pkg.packageJson.version;
+ logUtils.log(`Tagging '${dockerHubRepo}' docker image with version ${version}...`);
+ await execAsync(`docker tag ${dockerHubRepo} ${configs.DOCKER_HUB_ORG}/${dockerHubRepo}:${version}`);
+ await execAsync(`docker tag ${dockerHubRepo} ${configs.DOCKER_HUB_ORG}/${dockerHubRepo}:latest`);
+
+ // Publish to DockerHub
+ logUtils.log(`Pushing '${dockerHubRepo}' docker image to DockerHub...`);
+ await execAsync(`docker push ${configs.DOCKER_HUB_ORG}/${dockerHubRepo}:${version}`);
+ await execAsync(`docker push ${configs.DOCKER_HUB_ORG}/${dockerHubRepo}:latest`);
+ }
+}
+
function getPackagesWithDocs(allUpdatedPackages: Package[]): Package[] {
const rootPackageJsonPath = `${constants.monorepoRootPath}/package.json`;
const rootPackageJson = JSON.parse(fs.readFileSync(rootPackageJsonPath).toString());
diff --git a/packages/monorepo-scripts/src/types.ts b/packages/monorepo-scripts/src/types.ts
index 3c2ec5069..4af4fd257 100644
--- a/packages/monorepo-scripts/src/types.ts
+++ b/packages/monorepo-scripts/src/types.ts
@@ -41,7 +41,11 @@ export interface PackageJSON {
main?: string;
scripts?: { [command: string]: string };
config?: {
- additionalTsTypings?: string[];
+ postpublish?: {
+ assets?: string[];
+ docOmitExports?: string[];
+ dockerHubRepo?: string;
+ };
};
}
diff --git a/packages/monorepo-scripts/src/utils/configs.ts b/packages/monorepo-scripts/src/utils/configs.ts
index e579bdb7c..b6b6e2c5e 100644
--- a/packages/monorepo-scripts/src/utils/configs.ts
+++ b/packages/monorepo-scripts/src/utils/configs.ts
@@ -5,4 +5,5 @@ const REMOTE_NPM_REGISTRY_URL = 'https://registry.npmjs.org';
export const configs = {
IS_LOCAL_PUBLISH,
NPM_REGISTRY_URL: IS_LOCAL_PUBLISH ? LOCAL_NPM_REGISTRY_URL : REMOTE_NPM_REGISTRY_URL,
+ DOCKER_HUB_ORG: '0xorg',
};
diff --git a/packages/monorepo-scripts/src/utils/docker_hub_utils.ts b/packages/monorepo-scripts/src/utils/docker_hub_utils.ts
new file mode 100644
index 000000000..62215a579
--- /dev/null
+++ b/packages/monorepo-scripts/src/utils/docker_hub_utils.ts
@@ -0,0 +1,65 @@
+import { fetchAsync } from '@0x/utils';
+import { exec as execAsync } from 'promisify-child-process';
+
+import { utils } from './utils';
+
+const API_ENDPOINT = 'https://hub.docker.com/v2';
+const HTTP_OK_STATUS = 200;
+
+export const dockerHubUtils = {
+ async getTokenAsync(): Promise<string> {
+ const payload = {
+ username: process.env.DOCKER_USERNAME,
+ password: process.env.DOCKER_PASS,
+ };
+ const response = await fetchAsync(`${API_ENDPOINT}/users/login`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(payload),
+ });
+ if (response.status !== HTTP_OK_STATUS) {
+ throw new Error(
+ `DockerHub user login failed (status code: ${
+ response.status
+ }). Make sure you have environment variables 'DOCKER_USERNAME; and 'DOCKER_PASS' set`,
+ );
+ }
+ const respPayload = await response.json();
+ const token = respPayload.token;
+ return token;
+ },
+ async checkUserAddedToOrganizationOrThrowAsync(organization: string): Promise<void> {
+ utils.log('Checking that the user was added to the 0xorg DockerHub organization...');
+ const token = await dockerHubUtils.getTokenAsync();
+ const response = await fetchAsync(`${API_ENDPOINT}/repositories/${organization}/?page_size=10`, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ Authorization: `JWT ${token}`,
+ },
+ });
+ const respPayload = await response.json();
+ if (response.status !== HTTP_OK_STATUS || respPayload.count === 0) {
+ throw new Error(
+ `Failed to fetch org: ${organization}'s list of repos (status code: ${
+ response.status
+ }). Make sure your account has been added to the '${organization}' org on DockerHub`,
+ );
+ }
+ },
+ async loginUserToDockerCommandlineOrThrowAsync(): Promise<void> {
+ try {
+ utils.log('Checking that the user is logged in to docker command...');
+ await execAsync(`echo "$DOCKER_PASS" | docker login -u $DOCKER_USERNAME --password-stdin`);
+ } catch (err) {
+ throw new Error(
+ `Failed to log you into the 'docker' commandline tool. Make sure you have the 'docker' commandline tool installed. Full error: ${
+ err.message
+ }`,
+ );
+ }
+ },
+};