diff options
Diffstat (limited to 'packages/monorepo-scripts')
-rw-r--r-- | packages/monorepo-scripts/package.json | 2 | ||||
-rw-r--r-- | packages/monorepo-scripts/src/prepublish_checks.ts | 8 | ||||
-rw-r--r-- | packages/monorepo-scripts/src/publish.ts | 45 | ||||
-rw-r--r-- | packages/monorepo-scripts/src/types.ts | 6 | ||||
-rw-r--r-- | packages/monorepo-scripts/src/utils/configs.ts | 1 | ||||
-rw-r--r-- | packages/monorepo-scripts/src/utils/docker_hub_utils.ts | 65 | ||||
-rw-r--r-- | packages/monorepo-scripts/src/utils/utils.ts | 2 |
7 files changed, 124 insertions, 5 deletions
diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json index e18aa1d2f..187a80c93 100644 --- a/packages/monorepo-scripts/package.json +++ b/packages/monorepo-scripts/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@0x/monorepo-scripts", - "version": "1.0.18", + "version": "1.0.19", "engines": { "node": ">=6.12" }, 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 + }`, + ); + } + }, +}; diff --git a/packages/monorepo-scripts/src/utils/utils.ts b/packages/monorepo-scripts/src/utils/utils.ts index 95b187cc2..28c5658f3 100644 --- a/packages/monorepo-scripts/src/utils/utils.ts +++ b/packages/monorepo-scripts/src/utils/utils.ts @@ -106,8 +106,10 @@ export const utils = { return nextVersionIfValid; }, async getRemoteGitTagsAsync(): Promise<string[]> { + const TEN_MEGA_BYTES = 1024 * 1024 * 10; // tslint:disable-line custom-no-magic-numbers const result = await execAsync(`git ls-remote --tags`, { cwd: constants.monorepoRootPath, + maxBuffer: TEN_MEGA_BYTES, }); const tagsString = result.stdout; const tagOutputs: string[] = tagsString.split('\n'); |