From 73ef864979b4ab21b81c587154bfd5961ade734b Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 5 Mar 2019 08:56:29 +0100 Subject: [PATCH 1/5] Minor refactor of cli tasks (core start, gui publishing) --- package.json | 15 ++-- scripts/cli/index.ts | 66 +++++++++------ scripts/cli/tasks/core.start.ts | 41 +++++---- scripts/cli/tasks/grafanaui.build.ts | 101 +++++++++------------- scripts/cli/tasks/grafanaui.release.ts | 111 +++++++++++++------------ scripts/cli/tasks/task.ts | 23 +++++ scripts/cli/utils/execTask.ts | 17 +++- scripts/cli/utils/startSpinner.ts | 7 -- scripts/cli/utils/useSpinner.ts | 20 +++++ 9 files changed, 219 insertions(+), 182 deletions(-) create mode 100644 scripts/cli/tasks/task.ts delete mode 100644 scripts/cli/utils/startSpinner.ts create mode 100644 scripts/cli/utils/useSpinner.ts diff --git a/package.json b/package.json index 9e0b88804fd..c5136cf5e02 100644 --- a/package.json +++ b/package.json @@ -123,10 +123,10 @@ }, "scripts": { "dev": "webpack --progress --colors --mode development --config scripts/webpack/webpack.dev.js", - "start": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --theme", - "start:hot": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --hot --theme", - "start:ignoreTheme": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --hot", - "watch": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --theme -d watch,start", + "start": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts core:start --watchTheme", + "start:hot": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts core:start --hot --watchTheme", + "start:ignoreTheme": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts core:start --hot", + "watch": "yarn start -d watch,start core:start --watchTheme ", "build": "grunt build", "test": "grunt test", "tslint": "tslint -c tslint.json --project tsconfig.json", @@ -136,8 +136,11 @@ "storybook": "cd packages/grafana-ui && yarn storybook", "themes:generate": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/generateSassVariableFiles.ts", "prettier:check": "prettier --list-different \"**/*.{ts,tsx,scss}\"", - "gui:build": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --build", - "gui:release": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --release" + "gui:build": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts gui:build", + "gui:releasePrepare": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts gui:release", + "gui:publish": "cd packages/grafana-ui/dist && npm publish --access public", + "gui:release": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts gui:release -p", + "cli:help": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --help" }, "husky": { "hooks": { diff --git a/scripts/cli/index.ts b/scripts/cli/index.ts index f980944e2cd..3e54dc97a07 100644 --- a/scripts/cli/index.ts +++ b/scripts/cli/index.ts @@ -1,33 +1,47 @@ import program from 'commander'; -import chalk from 'chalk'; 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'; -export type Task = (options: T) => Promise; +program.option('-d, --depreciate ', 'Inform about npm script deprecation', v => v.split(',')); -// TODO: Refactor to commander commands -// This will enable us to have command scoped options and limit the ifs below program - .option('-h, --hot', 'Runs front-end with hot reload enabled') - .option('-t, --theme', 'Watches for theme changes and regenerates variables.scss files') - .option('-d, --depreciate ', 'Inform about npm script deprecation', v => v.split(',')) - .option('-b, --build', 'Created @grafana/ui build') - .option('-r, --release', 'Releases @grafana/ui to npm') - .parse(process.argv); - -if (program.build) { - execTask('grafanaui.build'); -} else if (program.release) { - execTask('grafanaui.release'); -} else { - if (program.depreciate && program.depreciate.length === 2) { - console.log( - chalk.yellow.bold( - `[NPM script depreciation] ${program.depreciate[0]} is deprecated! Use ${program.depreciate[1]} instead!` - ) - ); - } - execTask('core.start', { - watchThemes: !!program.theme, - hot: !!program.hot, + .command('core:start') + .option('-h, --hot', 'Run front-end with HRM enabled') + .option('-t, --watchTheme', 'Watch for theme changes and regenerate variables.scss files') + .description('Starts Grafana front-end in development mode with watch enabled') + .action(async cmd => { + await execTask(startTask)({ + watchThemes: cmd.theme, + hot: cmd.hot, + }); }); + +program + .command('gui:build') + .description('Builds @grafana/ui package to packages/grafana-ui/dist') + .action(async cmd => { + 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') + .action(async cmd => { + await execTask(releaseTask)({ + publishToNpm: !!cmd.publish, + }); + }); + +program.parse(process.argv); + +if (program.depreciate && program.depreciate.length === 2) { + console.log( + chalk.yellow.bold( + `[NPM script depreciation] ${program.depreciate[0]} is deprecated! Use ${program.depreciate[1]} instead!` + ) + ); } diff --git a/scripts/cli/tasks/core.start.ts b/scripts/cli/tasks/core.start.ts index 4e546c71b8c..dbd2dfe7119 100644 --- a/scripts/cli/tasks/core.start.ts +++ b/scripts/cli/tasks/core.start.ts @@ -1,35 +1,30 @@ import concurrently from 'concurrently'; -import { Task } from '..'; +import { Task, TaskRunner } from './task'; interface StartTaskOptions { watchThemes: boolean; hot: boolean; } -const startTask: Task = async ({ watchThemes, hot }) => { - const jobs = []; - - if (watchThemes) { - jobs.push({ +const startTaskRunner: TaskRunner = async ({ watchThemes, hot }) => { + const jobs = [ + watchThemes && { command: 'nodemon -e ts -w ./packages/grafana-ui/src/themes -x yarn run themes:generate', name: 'SASS variables generator', - }); - } - - if (!hot) { - jobs.push({ - command: 'webpack --progress --colors --watch --mode development --config scripts/webpack/webpack.dev.js', - name: 'Webpack', - }); - } else { - jobs.push({ - command: 'webpack-dev-server --progress --colors --mode development --config scripts/webpack/webpack.hot.js', - name: 'Dev server', - }); - } + }, + hot + ? { + command: 'webpack-dev-server --progress --colors --mode development --config scripts/webpack/webpack.hot.js', + name: 'Dev server', + } + : { + command: 'webpack --progress --colors --watch --mode development --config scripts/webpack/webpack.dev.js', + name: 'Webpack', + }, + ]; try { - await concurrently(jobs, { + await concurrently(jobs.filter(job => !!job), { killOthers: ['failure', 'failure'], }); } catch (e) { @@ -38,4 +33,6 @@ const startTask: Task = async ({ watchThemes, hot }) => { } }; -export default startTask; +export const startTask = new Task(); +startTask.setName('Core startTask'); +startTask.setRunner(startTaskRunner); diff --git a/scripts/cli/tasks/grafanaui.build.ts b/scripts/cli/tasks/grafanaui.build.ts index f892c13e115..6fce809bef9 100644 --- a/scripts/cli/tasks/grafanaui.build.ts +++ b/scripts/cli/tasks/grafanaui.build.ts @@ -1,95 +1,66 @@ import execa from 'execa'; import fs from 'fs'; -import { Task } from '..'; import { changeCwdToGrafanaUi, restoreCwd } from '../utils/cwd'; import chalk from 'chalk'; -import { startSpinner } from '../utils/startSpinner'; +import { useSpinner } from '../utils/useSpinner'; +import { Task, TaskRunner } from './task'; let distDir, cwd; -const clean = async () => { - const spinner = startSpinner('Cleaning'); - try { - await execa('npm', ['run', 'clean']); - spinner.succeed(); - } catch (e) { - spinner.fail(); - throw e; - } -}; +const clean = useSpinner('Cleaning', async () => await execa('npm', ['run', 'clean'])); -const compile = async () => { - const spinner = startSpinner('Compiling sources'); - try { - await execa('tsc', ['-p', './tsconfig.build.json']); - spinner.succeed(); - } catch (e) { - console.log(e); - spinner.fail(); - } -}; +const compile = useSpinner('Compiling sources', () => execa('tsc', ['-p', './tsconfig.build.json'])); -const rollup = async () => { - const spinner = startSpinner('Bundling'); - - try { - await execa('npm', ['run', 'build']); - spinner.succeed(); - } catch (e) { - spinner.fail(); - } -}; - -export const savePackage = async (path, pkg) => { - const spinner = startSpinner('Updating package.json'); +const rollup = useSpinner('Bundling', () => execa('npm', ['run', 'build'])); +export const savePackage = useSpinner<{ + path: string; + pkg: {}; +}>('Updating package.json', async ({ path, pkg }) => { return new Promise((resolve, reject) => { fs.writeFile(path, JSON.stringify(pkg, null, 2), err => { if (err) { - spinner.fail(); - console.error(err); reject(err); return; } - spinner.succeed(); resolve(); }); }); -}; +}); const preparePackage = async pkg => { pkg.main = 'index.js'; pkg.types = 'index.d.ts'; - await savePackage(`${cwd}/dist/package.json`, pkg); -}; - -const moveFiles = async () => { - const files = ['README.md', 'CHANGELOG.md', 'index.js']; - const spinner = startSpinner(`Moving ${files.join(', ')} files`); - - const promises = files.map(file => { - return fs.copyFile(`${cwd}/${file}`, `${distDir}/${file}`, err => { - if (err) { - console.error(err); - return; - } - }); + await savePackage({ + path: `${cwd}/dist/package.json`, + pkg, }); - - try { - await Promise.all(promises); - spinner.succeed(); - } catch (e) { - spinner.fail(); - } }; -const buildTask: Task = async () => { +const moveFiles = () => { + const files = ['README.md', 'CHANGELOG.md', 'index.js']; + return useSpinner(`Moving ${files.join(', ')} files`, async () => { + const promises = files.map(file => { + return new Promise((resolve, reject) => { + fs.copyFile(`${cwd}/${file}`, `${distDir}/${file}`, err => { + if (err) { + reject(err); + return; + } + resolve(); + }); + }); + }); + + await Promise.all(promises); + })(); +}; + +const buildTaskRunner: TaskRunner = async () => { cwd = changeCwdToGrafanaUi(); distDir = `${cwd}/dist`; const pkg = require(`${cwd}/package.json`); - - console.log(chalk.yellow(`Building ${pkg.name} @ ${pkg.version}`)); + console.log(chalk.yellow(`Building ${pkg.name} (package.json version: ${pkg.version})`)); await clean(); await compile(); @@ -100,4 +71,6 @@ const buildTask: Task = async () => { restoreCwd(); }; -export default buildTask; +export const buildTask = new Task(); +buildTask.setName('@grafana/ui build'); +buildTask.setRunner(buildTaskRunner); diff --git a/scripts/cli/tasks/grafanaui.release.ts b/scripts/cli/tasks/grafanaui.release.ts index 412c96e7fb5..b363ace35e0 100644 --- a/scripts/cli/tasks/grafanaui.release.ts +++ b/scripts/cli/tasks/grafanaui.release.ts @@ -1,14 +1,18 @@ import execa from 'execa'; -import { Task } from '..'; import { execTask } from '../utils/execTask'; import { changeCwdToGrafanaUiDist, changeCwdToGrafanaUi } from '../utils/cwd'; import semver from 'semver'; import inquirer from 'inquirer'; import chalk from 'chalk'; -import { startSpinner } from '../utils/startSpinner'; -import { savePackage } from './grafanaui.build'; +import { useSpinner } from '../utils/useSpinner'; +import { savePackage, buildTask } from './grafanaui.build'; +import { TaskRunner, Task } from './task'; -type VersionBumpType = 'patch' | 'minor' | 'major'; +type VersionBumpType = 'prerelease' | 'patch' | 'minor' | 'major'; + +interface ReleaseTaskOptions { + publishToNpm: boolean; +} const promptBumpType = async () => { return inquirer.prompt<{ type: VersionBumpType }>([ @@ -16,7 +20,7 @@ const promptBumpType = async () => { type: 'list', message: 'Select version bump', name: 'type', - choices: ['patch', 'minor', 'major'], + choices: ['prerelease', 'patch', 'minor', 'major'], validate: answer => { if (answer.length < 1) { return 'You must choose something'; @@ -28,13 +32,13 @@ const promptBumpType = async () => { ]); }; -const promptPrereleaseId = async () => { +const promptPrereleaseId = async (message = 'Is this a prerelease?', allowNo = true) => { return inquirer.prompt<{ id: string }>([ { type: 'list', - message: 'Is this a prerelease?', + message: message, name: 'id', - choices: ['no', 'alpha', 'beta'], + choices: allowNo ? ['no', 'alpha', 'beta'] : ['alpha', 'beta'], validate: answer => { if (answer.length < 1) { return 'You must choose something'; @@ -57,47 +61,31 @@ const promptConfirm = async (message?: string) => { ]); }; -const bumpVersion = async (version: string) => { - const spinner = startSpinner(`Saving version ${version} to package.json`); - changeCwdToGrafanaUi(); - - try { +const bumpVersion = (version: string) => + useSpinner(`Saving version ${version} to package.json`, async () => { + changeCwdToGrafanaUi(); await execa('npm', ['version', version]); - spinner.succeed(); - } catch (e) { - console.log(e); - spinner.fail(); - } + changeCwdToGrafanaUiDist(); + const pkg = require(`${process.cwd()}/package.json`); + pkg.version = version; + await savePackage({ path: `${process.cwd()}/package.json`, pkg }); + })(); - changeCwdToGrafanaUiDist(); - const pkg = require(`${process.cwd()}/package.json`); - pkg.version = version; - await savePackage(`${process.cwd()}/package.json`, pkg); -}; +const publishPackage = (name: string, version: string) => + useSpinner(`Publishing ${name} @ ${version} to npm registry...`, async () => { + changeCwdToGrafanaUiDist(); + console.log(chalk.yellowBright.bold(`\nReview dist package.json before proceeding!\n`)); + const { confirmed } = await promptConfirm('Are you ready to publish to npm?'); -const publishPackage = async (name: string, version: string) => { - changeCwdToGrafanaUiDist(); - console.log(chalk.yellowBright.bold(`\nReview dist package.json before proceeding!\n`)); - const { confirmed } = await promptConfirm('Are you ready to publish to npm?'); - - if (!confirmed) { - process.exit(); - } - - const spinner = startSpinner(`Publishing ${name} @ ${version} to npm registry...`); - - try { + if (!confirmed) { + process.exit(); + } await execa('npm', ['publish', '--access', 'public']); - spinner.succeed(); - } catch (e) { - console.log(e); - spinner.fail(); - process.exit(1); - } -}; + })(); + +const releaseTaskRunner: TaskRunner = async ({ publishToNpm }) => { + await execTask(buildTask)(); -const releaseTask: Task = async () => { - await execTask('grafanaui.build'); let releaseConfirmed = false; let nextVersion; changeCwdToGrafanaUiDist(); @@ -108,12 +96,17 @@ const releaseTask: Task = async () => { do { const { type } = await promptBumpType(); - const { id } = await promptPrereleaseId(); - - if (id !== 'no') { - nextVersion = semver.inc(pkg.version, `pre${type}`, id); + console.log(type); + if (type === 'prerelease') { + const { id } = await promptPrereleaseId('What kind of prerelease?', false); + nextVersion = semver.inc(pkg.version, type, id); } else { - nextVersion = semver.inc(pkg.version, type); + const { id } = await promptPrereleaseId(); + if (id !== 'no') { + nextVersion = semver.inc(pkg.version, `pre${type}`, id); + } else { + nextVersion = semver.inc(pkg.version, type); + } } console.log(chalk.yellowBright.bold(`You are going to release a new version of ${pkg.name}`)); @@ -124,10 +117,22 @@ const releaseTask: Task = async () => { } while (!releaseConfirmed); await bumpVersion(nextVersion); - 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 - COMMIT THIS FILE!`)); + if (publishToNpm) { + 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 - COMMIT THIS FILE!`)); + 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 default releaseTask; +export const releaseTask = new Task(); +releaseTask.setName('@grafana/ui release'); +releaseTask.setRunner(releaseTaskRunner); diff --git a/scripts/cli/tasks/task.ts b/scripts/cli/tasks/task.ts new file mode 100644 index 00000000000..d88860b7017 --- /dev/null +++ b/scripts/cli/tasks/task.ts @@ -0,0 +1,23 @@ +export type TaskRunner = (options: T) => Promise; + +export class Task { + name: string; + runner: (options: TOptions) => Promise; + options: TOptions; + + setName = name => { + this.name = name; + }; + + setRunner = (runner: TaskRunner) => { + this.runner = runner; + }; + + setOptions = options => { + this.options = options; + }; + + exec = () => { + return this.runner(this.options); + }; +} diff --git a/scripts/cli/utils/execTask.ts b/scripts/cli/utils/execTask.ts index 36071134331..f404206b7a9 100644 --- a/scripts/cli/utils/execTask.ts +++ b/scripts/cli/utils/execTask.ts @@ -1,6 +1,15 @@ -import { Task } from '..'; +import { Task } from '../tasks/task'; +import chalk from 'chalk'; -export const execTask = async (taskName, options?: T) => { - const task = await import(`${__dirname}/../tasks/${taskName}.ts`); - return task.default(options) as Task; +export const execTask = (task: Task) => async (options: TOptions) => { + console.log(chalk.yellow(`Running ${chalk.bold(task.name)} task`)); + task.setOptions(options); + try { + console.group(); + await task.exec(); + console.groupEnd(); + } catch (e) { + console.log(e); + process.exit(1); + } }; diff --git a/scripts/cli/utils/startSpinner.ts b/scripts/cli/utils/startSpinner.ts deleted file mode 100644 index ce895dec722..00000000000 --- a/scripts/cli/utils/startSpinner.ts +++ /dev/null @@ -1,7 +0,0 @@ -import ora from 'ora'; - -export const startSpinner = (label: string) => { - const spinner = new ora(label); - spinner.start(); - return spinner; -}; diff --git a/scripts/cli/utils/useSpinner.ts b/scripts/cli/utils/useSpinner.ts new file mode 100644 index 00000000000..48167e4ec2a --- /dev/null +++ b/scripts/cli/utils/useSpinner.ts @@ -0,0 +1,20 @@ +import ora from 'ora'; + +type FnToSpin = (options: T) => Promise; + +export const useSpinner = (spinnerLabel: string, fn: FnToSpin, killProcess = true) => { + return async (options: T) => { + const spinner = new ora(spinnerLabel); + spinner.start(); + try { + await fn(options); + spinner.succeed(); + } catch (e) { + spinner.fail(); + console.log(e); + if (killProcess) { + process.exit(1); + } + } + }; +}; From 18999df716df44337406bb6c47157be4527e61cb Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 5 Mar 2019 21:12:21 +0100 Subject: [PATCH 2/5] Ensuring master branch when performing release --- scripts/cli/tasks/grafanaui.release.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/cli/tasks/grafanaui.release.ts b/scripts/cli/tasks/grafanaui.release.ts index b363ace35e0..0a36a00bca7 100644 --- a/scripts/cli/tasks/grafanaui.release.ts +++ b/scripts/cli/tasks/grafanaui.release.ts @@ -83,7 +83,19 @@ const publishPackage = (name: string, version: string) => await execa('npm', ['publish', '--access', 'public']); })(); +const ensureMasterBranch = async () => { + const currentBranch = await execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']); + const status = await execa.stdout('git', ['status', '--porcelain']); + console.log(status === ''); + + 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 }) => { + await ensureMasterBranch(); await execTask(buildTask)(); let releaseConfirmed = false; From b816b4e2596b3e612d6bc4837ddb7f09f95eea2d Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 5 Mar 2019 21:16:34 +0100 Subject: [PATCH 3/5] Remove log --- scripts/cli/tasks/grafanaui.release.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/cli/tasks/grafanaui.release.ts b/scripts/cli/tasks/grafanaui.release.ts index 0a36a00bca7..2ebd2162e5b 100644 --- a/scripts/cli/tasks/grafanaui.release.ts +++ b/scripts/cli/tasks/grafanaui.release.ts @@ -86,7 +86,6 @@ const publishPackage = (name: string, version: string) => const ensureMasterBranch = async () => { const currentBranch = await execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']); const status = await execa.stdout('git', ['status', '--porcelain']); - console.log(status === ''); if (currentBranch !== 'master' && status !== '') { console.error(chalk.red.bold('You need to be on clean master branch to release @grafana/ui')); From 358f9cbeaeebc5a52ee3a770bd8fcd4a2b40ecdd Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 5 Mar 2019 21:18:26 +0100 Subject: [PATCH 4/5] Ensure clean master only when publishing package to npm --- scripts/cli/tasks/grafanaui.release.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/cli/tasks/grafanaui.release.ts b/scripts/cli/tasks/grafanaui.release.ts index 2ebd2162e5b..ef3430eaf9e 100644 --- a/scripts/cli/tasks/grafanaui.release.ts +++ b/scripts/cli/tasks/grafanaui.release.ts @@ -94,7 +94,10 @@ const ensureMasterBranch = async () => { }; const releaseTaskRunner: TaskRunner = async ({ publishToNpm }) => { - await ensureMasterBranch(); + if (publishToNpm) { + await ensureMasterBranch(); + } + await execTask(buildTask)(); let releaseConfirmed = false; From 3fc24fa964f57974591556810fcbeb5542c9b316 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Wed, 6 Mar 2019 09:52:31 +0100 Subject: [PATCH 5/5] Enable @grafana/ui version bump based on package.json contents --- scripts/cli/index.ts | 2 ++ scripts/cli/tasks/grafanaui.release.ts | 39 +++++++++++++++++--------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/scripts/cli/index.ts b/scripts/cli/index.ts index 3e54dc97a07..559f7295ad0 100644 --- a/scripts/cli/index.ts +++ b/scripts/cli/index.ts @@ -30,9 +30,11 @@ 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') .action(async cmd => { await execTask(releaseTask)({ publishToNpm: !!cmd.publish, + usePackageJsonVersion: !!cmd.usePackageJsonVersion, }); }); diff --git a/scripts/cli/tasks/grafanaui.release.ts b/scripts/cli/tasks/grafanaui.release.ts index ef3430eaf9e..a7fb8e4d6ea 100644 --- a/scripts/cli/tasks/grafanaui.release.ts +++ b/scripts/cli/tasks/grafanaui.release.ts @@ -12,6 +12,7 @@ type VersionBumpType = 'prerelease' | 'patch' | 'minor' | 'major'; interface ReleaseTaskOptions { publishToNpm: boolean; + usePackageJsonVersion: boolean; } const promptBumpType = async () => { @@ -93,7 +94,7 @@ const ensureMasterBranch = async () => { } }; -const releaseTaskRunner: TaskRunner = async ({ publishToNpm }) => { +const releaseTaskRunner: TaskRunner = async ({ publishToNpm, usePackageJsonVersion }) => { if (publishToNpm) { await ensureMasterBranch(); } @@ -109,28 +110,40 @@ const releaseTaskRunner: TaskRunner = async ({ publishToNpm console.log(`Current version: ${pkg.version}`); do { - const { type } = await promptBumpType(); - console.log(type); - if (type === 'prerelease') { - const { id } = await promptPrereleaseId('What kind of prerelease?', false); - nextVersion = semver.inc(pkg.version, type, id); - } else { - const { id } = await promptPrereleaseId(); - if (id !== 'no') { - nextVersion = semver.inc(pkg.version, `pre${type}`, id); + if (!usePackageJsonVersion) { + const { type } = await promptBumpType(); + console.log(type); + if (type === 'prerelease') { + const { id } = await promptPrereleaseId('What kind of prerelease?', false); + nextVersion = semver.inc(pkg.version, type, id); } else { - nextVersion = semver.inc(pkg.version, type); + const { id } = await promptPrereleaseId(); + if (id !== 'no') { + nextVersion = semver.inc(pkg.version, `pre${type}`, id); + } else { + nextVersion = semver.inc(pkg.version, type); + } } + } else { + nextVersion = pkg.version; } console.log(chalk.yellowBright.bold(`You are going to release a new version of ${pkg.name}`)); - console.log(chalk.green(`Version bump: ${pkg.version} ->`), chalk.bold.yellowBright(`${nextVersion}`)); + + 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}`)); + } + const { confirmed } = await promptConfirm(); releaseConfirmed = confirmed; } while (!releaseConfirmed); - await bumpVersion(nextVersion); + if (!usePackageJsonVersion) { + await bumpVersion(nextVersion); + } if (publishToNpm) { await publishPackage(pkg.name, nextVersion);