diff --git a/lerna.json b/lerna.json new file mode 100644 index 00000000000..cb26cf35b00 --- /dev/null +++ b/lerna.json @@ -0,0 +1,6 @@ +{ + "npmClient": "yarn", + "useWorkspaces": true, + "packages": ["packages/*"], + "version": "6.3.0" +} diff --git a/package.json b/package.json index 0f196c33afd..d54376900f0 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "husky": "1.3.1", "jest": "24.8.0", "jest-date-mock": "1.0.7", + "lerna": "^3.15.0", "lint-staged": "8.1.5", "load-grunt-tasks": "3.5.2", "mini-css-extract-plugin": "0.5.0", @@ -143,13 +144,10 @@ "storybook:build": "cd packages/grafana-ui && yarn storybook:build", "prettier:check": "prettier --list-different \"**/*.{ts,tsx,scss}\"", "prettier:write": "prettier --list-different \"**/*.{ts,tsx,scss}\" --write", - "gui:tslint": "tslint -c ./packages/grafana-ui/tslint.json --project ./packages/grafana-ui/tsconfig.json", - "gui:build": "grafana-toolkit gui:build", - "gui:releasePrepare": "grafana-toolkit gui:release", - "gui:publish": "cd packages/grafana-ui/dist && npm publish --access public", - "gui:release": "grafana-toolkit gui:release -p --createVersionCommit", "precommit": "grafana-toolkit precommit", - "themes:generate": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/generateSassVariableFiles.ts" + "themes:generate": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/generateSassVariableFiles.ts", + "packages:prepare": "lerna run clean && lerna run prepare", + "packages:publish": "lerna publish --contents dist --skip-git --skip-npm " }, "husky": { "hooks": { diff --git a/packages/grafana-data/CHANGELOG.md b/packages/grafana-data/CHANGELOG.md new file mode 100644 index 00000000000..556d4241a68 --- /dev/null +++ b/packages/grafana-data/CHANGELOG.md @@ -0,0 +1,3 @@ +# (2019-07-08) +First public release + diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index 86f13dce934..db7251574e6 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -10,7 +10,8 @@ "tslint": "tslint -c tslint.json --project tsconfig.json", "typecheck": "tsc --noEmit", "clean": "rimraf ./dist ./compiled", - "build": "rollup -c rollup.config.ts" + "build": "rollup -c rollup.config.ts", + "prepare": "grafana-toolkit package:build --scope=data" }, "author": "Grafana Labs", "license": "Apache-2.0", diff --git a/packages/grafana-runtime/CHANGELOG.md b/packages/grafana-runtime/CHANGELOG.md new file mode 100644 index 00000000000..556d4241a68 --- /dev/null +++ b/packages/grafana-runtime/CHANGELOG.md @@ -0,0 +1,3 @@ +# (2019-07-08) +First public release + diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index a811e9965aa..fb20c2c6551 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -12,7 +12,8 @@ "tslint": "tslint -c tslint.json --project tsconfig.json", "typecheck": "tsc --noEmit", "clean": "rimraf ./dist ./compiled", - "build": "rollup -c rollup.config.ts" + "build": "rollup -c rollup.config.ts", + "prepare": "grafana-toolkit package:build --scope=runtime" }, "author": "Grafana Labs", "license": "Apache-2.0", diff --git a/packages/grafana-runtime/rollup.config.ts b/packages/grafana-runtime/rollup.config.ts index a2d6da109d9..c18c1ab9871 100644 --- a/packages/grafana-runtime/rollup.config.ts +++ b/packages/grafana-runtime/rollup.config.ts @@ -20,7 +20,7 @@ const buildCjsPackage = ({ env }) => { globals: {}, }, ], - external: ['lodash'], // Use Lodash from grafana + external: ['lodash', '@grafana/ui'], // Use Lodash from grafana plugins: [ commonjs({ include: /node_modules/, diff --git a/packages/grafana-toolkit/package.json b/packages/grafana-toolkit/package.json index 8f6d65e710a..dc17bee258f 100644 --- a/packages/grafana-toolkit/package.json +++ b/packages/grafana-toolkit/package.json @@ -14,7 +14,8 @@ "tslint": "tslint -c tslint.json --project tsconfig.json", "typecheck": "tsc --noEmit", "precommit": "npm run tslint & npm run typecheck", - "clean": "rimraf ./dist ./compiled" + "clean": "rimraf ./dist ./compiled", + "prepare": "grafana-toolkit toolkit:build" }, "author": "Grafana Labs", "license": "Apache-2.0", diff --git a/packages/grafana-toolkit/src/cli/index.ts b/packages/grafana-toolkit/src/cli/index.ts index 423a14b4a58..17277a4b4bf 100644 --- a/packages/grafana-toolkit/src/cli/index.ts +++ b/packages/grafana-toolkit/src/cli/index.ts @@ -3,8 +3,6 @@ import program from 'commander'; import { execTask } from './utils/execTask'; import chalk from 'chalk'; import { startTask } from './tasks/core.start'; -import { buildTask } from './tasks/grafanaui.build'; -import { releaseTask } from './tasks/grafanaui.release'; import { changelogTask } from './tasks/changelog'; import { cherryPickTask } from './tasks/cherrypick'; import { precommitTask } from './tasks/precommit'; @@ -16,6 +14,7 @@ import { searchTestDataSetupTask } from './tasks/searchTestDataSetup'; import { closeMilestoneTask } from './tasks/closeMilestone'; import { pluginDevTask } from './tasks/plugin.dev'; import { pluginCITask } from './tasks/plugin.ci'; +import { buildPackageTask } from './tasks/package.build'; export const run = (includeInternalScripts = false) => { if (includeInternalScripts) { @@ -33,24 +32,12 @@ export const run = (includeInternalScripts = false) => { }); program - .command('gui:build') - .description('Builds @grafana/ui package to packages/grafana-ui/dist') + .command('package:build') + .option('-s, --scope ', 'packages=[data|runtime|ui|toolkit]') + .description('Builds @grafana/* package to packages/grafana-*/dist') .action(async cmd => { - // @ts-ignore - await execTask(buildTask)(); - }); - - program - .command('gui:release') - .description('Prepares @grafana/ui release (and publishes to npm on demand)') - .option('-p, --publish', 'Publish @grafana/ui to npm registry') - .option('-u, --usePackageJsonVersion', 'Use version specified in package.json') - .option('--createVersionCommit', 'Create and push version commit') - .action(async cmd => { - await execTask(releaseTask)({ - publishToNpm: !!cmd.publish, - usePackageJsonVersion: !!cmd.usePackageJsonVersion, - createVersionCommit: !!cmd.createVersionCommit, + await execTask(buildPackageTask)({ + scope: cmd.scope, }); }); diff --git a/packages/grafana-toolkit/src/cli/tasks/grafanaui.release.ts b/packages/grafana-toolkit/src/cli/tasks/grafanaui.release.ts index eb8da0da1c2..7eca80d25d1 100644 --- a/packages/grafana-toolkit/src/cli/tasks/grafanaui.release.ts +++ b/packages/grafana-toolkit/src/cli/tasks/grafanaui.release.ts @@ -1,190 +1,191 @@ -import execa = require('execa'); -import { execTask } from '../utils/execTask'; -import { changeCwdToGrafanaUiDist, changeCwdToGrafanaUi, restoreCwd } from '../utils/cwd'; -import { ReleaseType, inc } from 'semver'; -import { prompt } from 'inquirer'; -import chalk from 'chalk'; -import { useSpinner } from '../utils/useSpinner'; -import { savePackage, buildTask, clean } from './grafanaui.build'; -import { TaskRunner, Task } from './task'; +// import execa = require('execa'); +// import { execTask } from '../utils/execTask'; +// import { changeCwdToGrafanaUiDist, changeCwdToGrafanaUi, restoreCwd } from '../utils/cwd'; +// import { ReleaseType, inc } from 'semver'; +// import { prompt } from 'inquirer'; +// import chalk from 'chalk'; +// import { useSpinner } from '../utils/useSpinner'; +// import { savePackage, buildTask, clean } from './grafanaui.build'; +// import { TaskRunner, Task } from './task'; -type VersionBumpType = 'prerelease' | 'patch' | 'minor' | 'major'; +// type VersionBumpType = 'prerelease' | 'patch' | 'minor' | 'major'; -interface ReleaseTaskOptions { - publishToNpm: boolean; - usePackageJsonVersion: boolean; - createVersionCommit: boolean; -} +// interface ReleaseTaskOptions { +// publishToNpm: boolean; +// usePackageJsonVersion: boolean; +// createVersionCommit: boolean; +// } -const promptBumpType = async () => { - return prompt<{ type: VersionBumpType }>([ - { - type: 'list', - message: 'Select version bump', - name: 'type', - choices: ['prerelease', 'patch', 'minor', 'major'], - }, - ]); -}; +// const promptBumpType = async () => { +// return prompt<{ type: VersionBumpType }>([ +// { +// type: 'list', +// message: 'Select version bump', +// name: 'type', +// choices: ['prerelease', 'patch', 'minor', 'major'], +// }, +// ]); +// }; -const promptPrereleaseId = async (message = 'Is this a prerelease?', allowNo = true) => { - return prompt<{ id: string }>([ - { - type: 'list', - message: message, - name: 'id', - choices: allowNo ? ['no', 'alpha', 'beta'] : ['alpha', 'beta'], - }, - ]); -}; +// const promptPrereleaseId = async (message = 'Is this a prerelease?', allowNo = true) => { +// return prompt<{ id: string }>([ +// { +// type: 'list', +// message: message, +// name: 'id', +// choices: allowNo ? ['no', 'alpha', 'beta'] : ['alpha', 'beta'], +// }, +// ]); +// }; -const promptConfirm = async (message?: string) => { - return prompt<{ confirmed: boolean }>([ - { - type: 'confirm', - message: message || 'Is that correct?', - name: 'confirmed', - default: false, - }, - ]); -}; +// const promptConfirm = async (message?: string) => { +// return prompt<{ confirmed: boolean }>([ +// { +// type: 'confirm', +// message: message || 'Is that correct?', +// name: 'confirmed', +// default: false, +// }, +// ]); +// }; -// Since Grafana core depends on @grafana/ui highly, we run full check before release -const runChecksAndTests = async () => - // @ts-ignore - useSpinner(`Running checks and tests`, async () => { - try { - await execa('npm', ['run', 'test']); - } catch (e) { - console.log(e); - throw e; - } - })(); +// // Since Grafana core depends on @grafana/ui highly, we run full check before release +// const runChecksAndTests = async () => +// // @ts-ignore +// useSpinner(`Running checks and tests`, async () => { +// try { +// await execa('npm', ['run', 'test']); +// } catch (e) { +// console.log(e); -const bumpVersion = (version: string) => - // @ts-ignore - useSpinner(`Saving version ${version} to package.json`, async () => { - changeCwdToGrafanaUi(); - await execa('npm', ['version', version]); - changeCwdToGrafanaUiDist(); - const pkg = require(`${process.cwd()}/package.json`); - pkg.version = version; - await savePackage({ path: `${process.cwd()}/package.json`, pkg }); - })(); +// throw e; +// } +// })(); -const publishPackage = (name: string, version: string) => - // @ts-ignore - useSpinner(`Publishing ${name} @ ${version} to npm registry...`, async () => { - changeCwdToGrafanaUiDist(); - await execa('npm', ['publish', '--access', 'public']); - })(); +// const bumpVersion = (version: string) => +// // @ts-ignore +// useSpinner(`Saving version ${version} to package.json`, async () => { +// changeCwdToGrafanaUi(); +// await execa('npm', ['version', version]); +// changeCwdToGrafanaUiDist(); +// const pkg = require(`${process.cwd()}/package.json`); +// pkg.version = version; +// await savePackage({ path: `${process.cwd()}/package.json`, pkg }); +// })(); -const ensureMasterBranch = async () => { - const currentBranch = await execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']); - const status = await execa.stdout('git', ['status', '--porcelain']); +// const publishPackage = (name: string, version: string) => +// // @ts-ignore +// useSpinner(`Publishing ${name} @ ${version} to npm registry...`, async () => { +// changeCwdToGrafanaUiDist(); +// await execa('npm', ['publish', '--access', 'public']); +// })(); - if (currentBranch !== 'master' && status !== '') { - console.error(chalk.red.bold('You need to be on clean master branch to release @grafana/ui')); - process.exit(1); - } -}; +// const ensureMasterBranch = async () => { +// const currentBranch = await execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']); +// const status = await execa.stdout('git', ['status', '--porcelain']); -const prepareVersionCommitAndPush = async (version: string) => - // @ts-ignore - useSpinner('Commiting and pushing @grafana/ui version update', async () => { - await execa.stdout('git', ['commit', '-a', '-m', `Upgrade @grafana/ui version to v${version}`]); - await execa.stdout('git', ['push']); - })(); +// if (currentBranch !== 'master' && status !== '') { +// console.error(chalk.red.bold('You need to be on clean master branch to release @grafana/ui')); +// process.exit(1); +// } +// }; -const releaseTaskRunner: TaskRunner = async ({ - publishToNpm, - usePackageJsonVersion, - createVersionCommit, -}) => { - changeCwdToGrafanaUi(); - // @ts-ignore - await clean(); // Clean previous build if exists - restoreCwd(); +// const prepareVersionCommitAndPush = async (version: string) => +// // @ts-ignore +// useSpinner('Commiting and pushing @grafana/ui version update', async () => { +// await execa.stdout('git', ['commit', '-a', '-m', `Upgrade @grafana/ui version to v${version}`]); +// await execa.stdout('git', ['push']); +// })(); - if (publishToNpm) { - // TODO: Ensure release branch - // When need to update this when we star keeping @grafana/ui releases in sync with core - await ensureMasterBranch(); - } +// const releaseTaskRunner: TaskRunner = async ({ +// publishToNpm, +// usePackageJsonVersion, +// createVersionCommit, +// }) => { +// changeCwdToGrafanaUi(); +// // @ts-ignore +// await clean(); // Clean previous build if exists +// restoreCwd(); - await runChecksAndTests(); +// if (publishToNpm) { +// // TODO: Ensure release branch +// // When need to update this when we star keeping @grafana/ui releases in sync with core +// await ensureMasterBranch(); +// } - await execTask(buildTask)({} as any); +// await runChecksAndTests(); - let releaseConfirmed = false; - let nextVersion; - changeCwdToGrafanaUiDist(); +// await execTask(buildTask)({} as any); - const pkg = require(`${process.cwd()}/package.json`); +// let releaseConfirmed = false; +// let nextVersion; +// changeCwdToGrafanaUiDist(); - console.log(`Current version: ${pkg.version}`); +// const pkg = require(`${process.cwd()}/package.json`); - do { - if (!usePackageJsonVersion) { - const { type } = await promptBumpType(); - console.log(type); - if (type === 'prerelease') { - const { id } = await promptPrereleaseId('What kind of prerelease?', false); - nextVersion = inc(pkg.version, type, id as any); - } else { - const { id } = await promptPrereleaseId(); - if (id !== 'no') { - nextVersion = inc(pkg.version, `pre${type}` as ReleaseType, id as any); - } else { - nextVersion = inc(pkg.version, type as ReleaseType); - } - } - } else { - nextVersion = pkg.version; - } +// console.log(`Current version: ${pkg.version}`); - console.log(chalk.yellowBright.bold(`You are going to release a new version of ${pkg.name}`)); +// do { +// if (!usePackageJsonVersion) { +// const { type } = await promptBumpType(); +// console.log(type); +// if (type === 'prerelease') { +// const { id } = await promptPrereleaseId('What kind of prerelease?', false); +// nextVersion = inc(pkg.version, type, id as any); +// } else { +// const { id } = await promptPrereleaseId(); +// if (id !== 'no') { +// nextVersion = inc(pkg.version, `pre${type}` as ReleaseType, id as any); +// } else { +// nextVersion = inc(pkg.version, type as ReleaseType); +// } +// } +// } else { +// nextVersion = pkg.version; +// } - if (usePackageJsonVersion) { - console.log(chalk.green(`Version based on package.json: `), chalk.bold.yellowBright(`${nextVersion}`)); - } else { - console.log(chalk.green(`Version bump: ${pkg.version} ->`), chalk.bold.yellowBright(`${nextVersion}`)); - } +// console.log(chalk.yellowBright.bold(`You are going to release a new version of ${pkg.name}`)); - const { confirmed } = await promptConfirm(); +// if (usePackageJsonVersion) { +// console.log(chalk.green(`Version based on package.json: `), chalk.bold.yellowBright(`${nextVersion}`)); +// } else { +// console.log(chalk.green(`Version bump: ${pkg.version} ->`), chalk.bold.yellowBright(`${nextVersion}`)); +// } - releaseConfirmed = confirmed; - } while (!releaseConfirmed); +// const { confirmed } = await promptConfirm(); - if (!usePackageJsonVersion) { - await bumpVersion(nextVersion); - } +// releaseConfirmed = confirmed; +// } while (!releaseConfirmed); - if (createVersionCommit) { - await prepareVersionCommitAndPush(nextVersion); - } +// if (!usePackageJsonVersion) { +// await bumpVersion(nextVersion); +// } - if (publishToNpm) { - console.log(chalk.yellowBright.bold(`\nReview dist package.json before proceeding!\n`)); - const { confirmed } = await promptConfirm('Are you ready to publish to npm?'); +// if (createVersionCommit) { +// await prepareVersionCommitAndPush(nextVersion); +// } - if (!confirmed) { - process.exit(); - } +// if (publishToNpm) { +// console.log(chalk.yellowBright.bold(`\nReview dist package.json before proceeding!\n`)); +// const { confirmed } = await promptConfirm('Are you ready to publish to npm?'); - await publishPackage(pkg.name, nextVersion); - console.log(chalk.green(`\nVersion ${nextVersion} of ${pkg.name} succesfully released!`)); - console.log(chalk.yellow(`\nUpdated @grafana/ui/package.json with version bump created.`)); +// if (!confirmed) { +// process.exit(); +// } - process.exit(); - } else { - console.log( - chalk.green( - `\nVersion ${nextVersion} of ${pkg.name} succesfully prepared for release. See packages/grafana-ui/dist` - ) - ); - console.log(chalk.green(`\nTo publish to npm registry run`), chalk.bold.blue(`npm run gui:publish`)); - } -}; +// await publishPackage(pkg.name, nextVersion); +// console.log(chalk.green(`\nVersion ${nextVersion} of ${pkg.name} succesfully released!`)); +// console.log(chalk.yellow(`\nUpdated @grafana/ui/package.json with version bump created.`)); -export const releaseTask = new Task('@grafana/ui release', releaseTaskRunner); +// process.exit(); +// } else { +// console.log( +// chalk.green( +// `\nVersion ${nextVersion} of ${pkg.name} succesfully prepared for release. See packages/grafana-ui/dist` +// ) +// ); +// console.log(chalk.green(`\nTo publish to npm registry run`), chalk.bold.blue(`npm run gui:publish`)); +// } +// }; + +// export const releaseTask = new Task('@grafana/ui release', releaseTaskRunner); diff --git a/packages/grafana-toolkit/src/cli/tasks/grafanaui.build.ts b/packages/grafana-toolkit/src/cli/tasks/package.build.ts similarity index 59% rename from packages/grafana-toolkit/src/cli/tasks/grafanaui.build.ts rename to packages/grafana-toolkit/src/cli/tasks/package.build.ts index 6dbbc7b1d36..88c391b79a4 100644 --- a/packages/grafana-toolkit/src/cli/tasks/grafanaui.build.ts +++ b/packages/grafana-toolkit/src/cli/tasks/package.build.ts @@ -1,7 +1,9 @@ import execa = require('execa'); // @ts-ignore import * as fs from 'fs'; -import { changeCwdToGrafanaUi, restoreCwd } from '../utils/cwd'; +// @ts-ignore +import * as path from 'path'; +import { changeCwdToGrafanaUi, restoreCwd, changeCwdToPackage } from '../utils/cwd'; import chalk from 'chalk'; import { useSpinner } from '../utils/useSpinner'; import { Task, TaskRunner } from './task'; @@ -68,19 +70,34 @@ const moveFiles = () => { })(); }; -const buildTaskRunner: TaskRunner = async () => { - cwd = changeCwdToGrafanaUi(); - distDir = `${cwd}/dist`; - const pkg = require(`${cwd}/package.json`); - console.log(chalk.yellow(`Building ${pkg.name} (package.json version: ${pkg.version})`)); +interface PackageBuildOptions { + scope: string; +} - await clean(); - await compile(); - await rollup(); - await preparePackage(pkg); - await moveFiles(); +const buildTaskRunner: TaskRunner = async ({ scope }) => { + if (!scope) { + throw new Error('Provide packages with -s, --scope '); + } - restoreCwd(); + const scopes = scope.split(',').map(s => { + return async () => { + cwd = path.resolve(__dirname, `../../../../grafana-${s}`); + // Lerna executes this in package's dir context, but for testing purposes I want to be able to run from root: + // grafana-toolkit package:build --scope= + process.chdir(cwd); + distDir = `${cwd}/dist`; + const pkg = require(`${cwd}/package.json`); + console.log(chalk.yellow(`Building ${pkg.name} (package.json version: ${pkg.version})`)); + + await clean(); + await compile(); + await rollup(); + await preparePackage(pkg); + await moveFiles(); + }; + }); + + await Promise.all(scopes.map(s => s())); }; -export const buildTask = new Task('@grafana/ui build', buildTaskRunner); +export const buildPackageTask = new Task('@grafana/ui build', buildTaskRunner); diff --git a/packages/grafana-toolkit/src/cli/tasks/toolkit.build.ts b/packages/grafana-toolkit/src/cli/tasks/toolkit.build.ts index 61fd6fcaee0..0bee4054994 100644 --- a/packages/grafana-toolkit/src/cli/tasks/toolkit.build.ts +++ b/packages/grafana-toolkit/src/cli/tasks/toolkit.build.ts @@ -102,7 +102,7 @@ const copySassFiles = () => { }; const toolkitBuildTaskRunner: TaskRunner = async () => { - cwd = changeCwdToGrafanaToolkit(); + cwd = path.resolve(__dirname, '../../../'); distDir = `${cwd}/dist`; const pkg = require(`${cwd}/package.json`); console.log(chalk.yellow(`Building ${pkg.name} (package.json version: ${pkg.version})`)); @@ -114,7 +114,6 @@ const toolkitBuildTaskRunner: TaskRunner = async () => { fs.mkdirSync('./dist/sass'); await moveFiles(); await copySassFiles(); - restoreCwd(); }; export const toolkitBuildTask = new Task('@grafana/toolkit build', toolkitBuildTaskRunner); diff --git a/packages/grafana-toolkit/src/cli/utils/cwd.ts b/packages/grafana-toolkit/src/cli/utils/cwd.ts index 48ca39e5da2..836ebd0b608 100644 --- a/packages/grafana-toolkit/src/cli/utils/cwd.ts +++ b/packages/grafana-toolkit/src/cli/utils/cwd.ts @@ -17,3 +17,15 @@ export const changeCwdToGrafanaUiDist = () => { export const restoreCwd = () => { process.chdir(cwd); }; + +type PackageId = 'ui' | 'data' | 'runtime' | 'toolkit'; + +export const changeCwdToPackage = (scope: PackageId) => { + try { + process.chdir(`${cwd}/packages/grafana-${scope}`); + } catch (e) { + throw e; + } + + return process.cwd(); +}; diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 53728cb7b8f..dfb3bffdec4 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -14,7 +14,8 @@ "storybook": "start-storybook -p 9001 -c .storybook", "storybook:build": "build-storybook -o ./dist/storybook -c .storybook", "clean": "rimraf ./dist ./compiled", - "build": "rollup -c rollup.config.ts" + "build": "rollup -c rollup.config.ts", + "prepare": "grafana-toolkit package:build --scope=ui" }, "author": "Grafana Labs", "license": "Apache-2.0",