Toolkit: Remove deprecated plugin:build (#67485)
Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
This commit is contained in:
co-authored by
Jack Westbrook
parent
ea7e5e2d82
commit
50fb1497e5
@@ -1,7 +1,6 @@
|
||||
import chalk from 'chalk';
|
||||
import { program } from 'commander';
|
||||
|
||||
import { pluginBuildTask } from './tasks/plugin.build';
|
||||
import { getToolkitVersion } from './tasks/plugin.utils';
|
||||
import { templateTask } from './tasks/template';
|
||||
import { execTask } from './utils/execTask';
|
||||
@@ -13,7 +12,7 @@ export const run = (includeInternalScripts = false) => {
|
||||
program
|
||||
.command('debug:template')
|
||||
.description('Just testing')
|
||||
.action(async (cmd) => {
|
||||
.action(async () => {
|
||||
await execTask(templateTask)({});
|
||||
});
|
||||
}
|
||||
@@ -40,21 +39,12 @@ export const run = (includeInternalScripts = false) => {
|
||||
.option('--skipTest', 'Skip running tests (for pipelines that run it separate)', false)
|
||||
.option('--skipLint', 'Skip running lint (for pipelines that run it separate)', false)
|
||||
.option('--preserveConsole', 'Preserves console calls', false)
|
||||
.description('[Deprecated] Prepares plugin dist package')
|
||||
.action(async (cmd) => {
|
||||
console.log(chalk.yellow('\n⚠️ DEPRECATED. This command is deprecated and will be removed in v10. ⚠️'));
|
||||
.description('[removed] Use grafana create-plugin instead')
|
||||
.action(async () => {
|
||||
console.log(
|
||||
'Please migrate to grafana create-plugin https://github.com/grafana/plugin-tools/tree/main/packages/create-plugin\n'
|
||||
'No longer supported. Use grafana create-plugin https://github.com/grafana/plugin-tools/tree/main/packages/create-plugin\n'
|
||||
);
|
||||
|
||||
await execTask(pluginBuildTask)({
|
||||
coverage: cmd.coverage,
|
||||
silent: true,
|
||||
maxJestWorkers: cmd.maxJestWorkers,
|
||||
preserveConsole: cmd.preserveConsole,
|
||||
skipLint: cmd.skipLint,
|
||||
skipTest: cmd.skipTest,
|
||||
});
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
program
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
import { ESLint } from 'eslint';
|
||||
import execa from 'execa';
|
||||
import { constants as fsConstants, promises as fs } from 'fs';
|
||||
import globby from 'globby';
|
||||
import { resolve as resolvePath } from 'path';
|
||||
import rimrafCallback from 'rimraf';
|
||||
import { promisify } from 'util';
|
||||
|
||||
import { useSpinner } from '../utils/useSpinner';
|
||||
|
||||
import { bundlePlugin as bundleFn, PluginBundleOptions } from './plugin/bundle';
|
||||
import { testPlugin } from './plugin/tests';
|
||||
import { Task, TaskRunner } from './task';
|
||||
|
||||
const { access, copyFile } = fs;
|
||||
const { COPYFILE_EXCL } = fsConstants;
|
||||
const rimraf = promisify(rimrafCallback);
|
||||
|
||||
interface PluginBuildOptions {
|
||||
coverage: boolean;
|
||||
maxJestWorkers?: string;
|
||||
preserveConsole?: boolean;
|
||||
skipTest?: boolean;
|
||||
skipLint?: boolean;
|
||||
}
|
||||
|
||||
interface Fixable {
|
||||
fix?: boolean;
|
||||
}
|
||||
|
||||
const bundlePlugin = (options: PluginBundleOptions) => useSpinner('Compiling...', () => bundleFn(options));
|
||||
|
||||
// @ts-ignore
|
||||
const clean = () => useSpinner('Cleaning', () => rimraf(`${process.cwd()}/dist`));
|
||||
|
||||
const copyIfNonExistent = (srcPath: string, destPath: string) =>
|
||||
copyFile(srcPath, destPath, COPYFILE_EXCL)
|
||||
.then(() => console.log(`Created: ${destPath}`))
|
||||
.catch((error) => {
|
||||
if (error.code !== 'EEXIST') {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
export const prepare = () =>
|
||||
useSpinner('Preparing', () =>
|
||||
Promise.all([
|
||||
// Remove local dependencies for @grafana/data/node_modules
|
||||
// See: https://github.com/grafana/grafana/issues/26748
|
||||
rimraf(resolvePath(__dirname, 'node_modules/@grafana/data/node_modules')),
|
||||
// Copy only if local tsconfig does not exist. Otherwise this will work, but have odd behavior
|
||||
copyIfNonExistent(
|
||||
resolvePath(__dirname, '../../config/tsconfig.plugin.local.json'),
|
||||
resolvePath(process.cwd(), 'tsconfig.json')
|
||||
),
|
||||
// Copy only if local prettierrc does not exist. Otherwise this will work, but have odd behavior
|
||||
copyIfNonExistent(
|
||||
resolvePath(__dirname, '../../config/prettier.plugin.rc.js'),
|
||||
resolvePath(process.cwd(), '.prettierrc.js')
|
||||
),
|
||||
])
|
||||
);
|
||||
|
||||
export const versions = async () => {
|
||||
try {
|
||||
const nodeVersion = await execa('node', ['--version']);
|
||||
console.log(`Using Node.js ${nodeVersion.stdout}`);
|
||||
|
||||
const toolkitVersion = await execa('grafana-toolkit', ['--version']);
|
||||
console.log(`Using @grafana/toolkit ${toolkitVersion.stdout}`);
|
||||
} catch (err) {
|
||||
console.log(`Error reading versions`, err);
|
||||
}
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
const typecheckPlugin = () => useSpinner('Typechecking', () => execa('tsc', ['--noEmit']));
|
||||
|
||||
// @ts-ignore
|
||||
const getStylesSources = () => globby(resolvePath(process.cwd(), 'src/**/*.+(scss|css)'));
|
||||
|
||||
export const lintPlugin = ({ fix }: Fixable = {}) =>
|
||||
useSpinner('Linting', async () => {
|
||||
try {
|
||||
// Show a warning if the tslint file exists
|
||||
await access(resolvePath(process.cwd(), 'tslint.json'));
|
||||
console.log('\n');
|
||||
console.log('--------------------------------------------------------------');
|
||||
console.log('NOTE: @grafana/toolkit has migrated to use eslint');
|
||||
console.log('Update your configs to use .eslintrc rather than tslint.json');
|
||||
console.log('--------------------------------------------------------------');
|
||||
} catch {
|
||||
// OK: tslint does not exist
|
||||
}
|
||||
|
||||
// @todo should remove this because the config file could be in a parent dir or within package.json
|
||||
const configFile = await globby(resolvePath(process.cwd(), '.eslintrc?(.cjs|.js|.json|.yaml|.yml)')).then(
|
||||
(filePaths) => {
|
||||
if (filePaths.length > 0) {
|
||||
return filePaths[0];
|
||||
} else {
|
||||
return resolvePath(__dirname, '../../config/eslint.plugin.js');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const eslint = new ESLint({
|
||||
extensions: ['.ts', '.tsx'],
|
||||
overrideConfigFile: configFile,
|
||||
fix,
|
||||
useEslintrc: false,
|
||||
});
|
||||
|
||||
const results = await eslint.lintFiles(resolvePath(process.cwd(), 'src'));
|
||||
|
||||
if (fix) {
|
||||
await ESLint.outputFixes(results);
|
||||
}
|
||||
|
||||
const { errorCount, warningCount } = results.reduce<Record<string, number>>(
|
||||
(acc, value) => {
|
||||
acc.errorCount += value.errorCount;
|
||||
acc.warningCount += value.warningCount;
|
||||
return acc;
|
||||
},
|
||||
{ errorCount: 0, warningCount: 0 }
|
||||
);
|
||||
|
||||
const formatter = await eslint.loadFormatter('stylish');
|
||||
const resultText = formatter.format(results);
|
||||
|
||||
if (errorCount > 0 || warningCount > 0) {
|
||||
console.log('\n');
|
||||
console.log(resultText);
|
||||
console.log('\n');
|
||||
}
|
||||
|
||||
if (errorCount > 0) {
|
||||
throw new Error(`${errorCount} linting errors found in ${results.length} files`);
|
||||
}
|
||||
});
|
||||
|
||||
export const pluginBuildRunner: TaskRunner<PluginBuildOptions> = async ({
|
||||
coverage,
|
||||
maxJestWorkers,
|
||||
preserveConsole,
|
||||
skipTest,
|
||||
skipLint,
|
||||
}) => {
|
||||
await versions();
|
||||
await prepare();
|
||||
if (!skipLint) {
|
||||
await lintPlugin({ fix: false });
|
||||
}
|
||||
if (!skipTest) {
|
||||
await testPlugin({ updateSnapshot: false, coverage, maxWorkers: maxJestWorkers, watch: false });
|
||||
}
|
||||
await bundlePlugin({ watch: false, production: true, preserveConsole });
|
||||
};
|
||||
|
||||
export const pluginBuildTask = new Task<PluginBuildOptions>('Build plugin', pluginBuildRunner);
|
||||
@@ -1,79 +0,0 @@
|
||||
import clearConsole from 'react-dev-utils/clearConsole';
|
||||
import formatWebpackMessages from 'react-dev-utils/formatWebpackMessages';
|
||||
import webpack from 'webpack';
|
||||
|
||||
import { loadWebpackConfig } from '../../../config/webpack.plugin.config';
|
||||
|
||||
export interface PluginBundleOptions {
|
||||
watch: boolean;
|
||||
production?: boolean;
|
||||
preserveConsole?: boolean;
|
||||
}
|
||||
|
||||
export const bundlePlugin = async ({ watch, production, preserveConsole }: PluginBundleOptions) => {
|
||||
const compiler = webpack(
|
||||
await loadWebpackConfig({
|
||||
watch,
|
||||
production,
|
||||
preserveConsole,
|
||||
})
|
||||
);
|
||||
|
||||
const webpackPromise = new Promise<void>((resolve, reject) => {
|
||||
if (watch) {
|
||||
console.log('Started watching plugin for changes...');
|
||||
compiler.watch({ ignored: ['**/node_modules', '**/dist'] }, (err, stats) => {});
|
||||
|
||||
compiler.hooks.invalid.tap('invalid', () => {
|
||||
clearConsole();
|
||||
console.log('Compiling...');
|
||||
});
|
||||
|
||||
compiler.hooks.done.tap('done', (stats) => {
|
||||
clearConsole();
|
||||
const json = stats.toJson();
|
||||
const output = formatWebpackMessages(json);
|
||||
|
||||
if (!output.errors.length && !output.warnings.length) {
|
||||
console.log('Compiled successfully!\n');
|
||||
console.log(stats.toString({ colors: true }));
|
||||
}
|
||||
|
||||
if (output.errors.length) {
|
||||
console.log('Compilation failed!');
|
||||
output.errors.forEach((e) => console.log(e));
|
||||
|
||||
if (output.warnings.length) {
|
||||
console.log('Warnings:');
|
||||
output.warnings.forEach((w) => console.log(w));
|
||||
}
|
||||
}
|
||||
if (output.errors.length === 0 && output.warnings.length) {
|
||||
console.log('Compiled with warnings!');
|
||||
output.warnings.forEach((w) => console.log(w));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
compiler.run((err, stats) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats?.hasErrors()) {
|
||||
stats.compilation.errors.forEach((e) => {
|
||||
console.log(e.message);
|
||||
});
|
||||
|
||||
reject('Build failed');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n', stats?.toString({ colors: true }), '\n');
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return webpackPromise;
|
||||
};
|
||||
-1
@@ -1 +0,0 @@
|
||||
NOTE: not a real image, but should be excluded from hashed files
|
||||
@@ -1,50 +0,0 @@
|
||||
import { runCLI } from '@jest/core';
|
||||
|
||||
import { loadJestPluginConfig } from '../../../config/jest.plugin.config';
|
||||
import { useSpinner } from '../../utils/useSpinner';
|
||||
|
||||
export interface PluginTestOptions {
|
||||
updateSnapshot: boolean;
|
||||
coverage: boolean;
|
||||
watch: boolean;
|
||||
testPathPattern?: string;
|
||||
testNamePattern?: string;
|
||||
maxWorkers?: string;
|
||||
}
|
||||
|
||||
export const testPlugin = ({
|
||||
updateSnapshot,
|
||||
coverage,
|
||||
watch,
|
||||
testPathPattern,
|
||||
testNamePattern,
|
||||
maxWorkers,
|
||||
}: PluginTestOptions) =>
|
||||
useSpinner('Running tests', async () => {
|
||||
const testConfig = loadJestPluginConfig();
|
||||
|
||||
const cliConfig = {
|
||||
config: JSON.stringify(testConfig),
|
||||
updateSnapshot,
|
||||
coverage,
|
||||
watch,
|
||||
testPathPattern: testPathPattern ? [testPathPattern] : [],
|
||||
testNamePattern: testNamePattern ? [testNamePattern] : [],
|
||||
passWithNoTests: true,
|
||||
maxWorkers,
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
const runJest = () => runCLI(cliConfig, [process.cwd()]);
|
||||
|
||||
if (watch) {
|
||||
runJest();
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const results = await runJest();
|
||||
|
||||
if (results.results.numFailedTests > 0 || results.results.numFailedTestSuites > 0) {
|
||||
throw new Error('Tests failed');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
import ora from 'ora';
|
||||
|
||||
export const useSpinner = async (label: string, fn: () => Promise<any>, killProcess = true) => {
|
||||
const spinner = ora(label);
|
||||
spinner.start();
|
||||
try {
|
||||
await fn();
|
||||
spinner.succeed();
|
||||
} catch (err: any) {
|
||||
spinner.fail(err.message || err);
|
||||
|
||||
if (err.stdout) {
|
||||
console.error(err.stdout);
|
||||
} else if (err.message) {
|
||||
// Return stack trace if error object
|
||||
console.trace(err); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
if (killProcess) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user