Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: enable linking charts library to kibana #1164

Merged
merged 13 commits into from
May 27, 2021
Merged
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -468,5 +468,12 @@ module.exports = {
],
},
},
{
files: ['packages/link_kibana/**/*.js'],
rules: {
'no-console': 0,
'promise/no-promise-in-callback': 0,
},
},
],
};
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"build:compile": "echo 'Compiling...' && tsc -p ./tsconfig.lib.json && tsc -p ./tsconfig.lib-nocomments.json",
"build:sass": "echo 'Building sass...' && node-sass src/theme_light.scss dist/theme_light.css --output-style compressed && node-sass src/theme_dark.scss dist/theme_dark.css --output-style compressed && node-sass src/theme_only_light.scss dist/theme_only_light.css --output-style compressed && node-sass src/theme_only_dark.scss dist/theme_only_dark.css --output-style compressed",
"build:check": "echo 'Type checking dist...' && tsc -p ./tsconfig.lib-check.json",
"build:watch": "echo 'Watching build...' && yarn build:clean && yarn build:css && yarn build:compile -w ",
"build:watch": "echo 'Watching build...' && yarn build:clean && yarn build:css && tsc -p ./tsconfig.lib.json -w",
"concat:sass": "echo 'Concat SASS...' && node scripts/concat_sass.js",
"cz": "git-cz",
"lint": "NODE_ENV=production eslint --quiet --ext .tsx,.ts,.js .",
Expand Down Expand Up @@ -59,8 +59,7 @@
"typecheck:all": "tsc -p ./tsconfig.json --noEmit",
"ts:prune": "ts-prune",
"watch": "yarn test --watch",
"index:check": "ts-node scripts/index_check.ts",
"tsdocs:check": "ts-node scripts/tsdoc_check.ts"
"link:kibana": "node ./packages/link_kibana"
},
"dependencies": {
"@popperjs/core": "^2.4.0",
Expand Down Expand Up @@ -157,7 +156,7 @@
"eslint": "^7.17.0",
"eslint-config-airbnb-typescript": "^12.0.0",
"eslint-config-prettier": "^7.1.0",
"eslint-plugin-elastic-charts": "file:./packages/eslint-plugin-elastic-charts",
"eslint-plugin-elastic-charts": "link:./packages/eslint-plugin-elastic-charts",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-file-header": "^0.0.1",
"eslint-plugin-header": "^3.1.0",
Expand All @@ -177,6 +176,7 @@
"jest-matcher-utils": "^26.6.2",
"jest-puppeteer": "^4.4.0",
"jest-puppeteer-docker": "^1.4.2",
"link-kibana": "link:./packages/link_kibana",
"lint-staged": "^10.5.3",
"lodash": "^4.17.15",
"lorem-ipsum": "^2.0.3",
Expand Down
1 change: 1 addition & 0 deletions packages/eslint-plugin-elastic-charts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "eslint-plugin-elastic-charts",
"description": "Custom elastic-charts lint plugin",
"license": "Apache-2.0",
"version": "1.0.0",
"main": "index.js"
}
22 changes: 22 additions & 0 deletions packages/link_kibana/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

const main = require('./main');

void main();
257 changes: 257 additions & 0 deletions packages/link_kibana/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

const path = require('path');

const chalk = require('chalk');
const inquirer = require('inquirer');
const ora = require('ora');

const { spawnWatch, exec } = require('./process_utils');
const { replaceModules } = require('./replace_modules');
const {
getPackageInfo,
getTempDir,
getLinkInfo,
writeLinkInfo,
isLinked,
linkPackage,
unlinkPackage,
} = require('./utils');

/**
* This script is used to handling symlinking elastic charts to kibana.
* The cli walks you through the require parameters and runs the build
* in watch mode to facilitate the entire linking process.
*
* NOTE: This does **not** rebuild css files, only typescript files
*/
module.exports = async () => {
// child processes for cleanup
const cps = [];
const cleanExit = () => {
cps.forEach((cp) => cp && cp.kill());
process.exit(); // eslint-disable-line unicorn/no-process-exit
};
process.on('SIGINT', cleanExit); // catch ctrl-c
process.on('SIGTERM', cleanExit); // catch kill

const debug = process.argv.includes('--debug');
const echDir = process.cwd();
const echPackageContent = await getPackageInfo(echDir);
const packageName = echPackageContent.name;

if (packageName !== '@elastic/charts') {
if (packageName) throw new Error('This script is only designed for use with @elastic/charts');
throw new Error('No name defined in package.json');
}

const tempDir = await getTempDir(echDir, packageName);
const linkInfo = await getLinkInfo(tempDir);
const linkedPackages = ['react', 'react-dom', 'redux', 'react-redux'];

const { action } = await inquirer.prompt({
name: 'action',
message: 'Select action',
type: 'list',
default: 'link',
choices: ['Link', 'Unlink', 'Watch mode'],
});

if (action === 'Link') {
const { appLinkRelativePath } = await inquirer.prompt({
name: 'appLinkRelativePath',
message: 'Enter path to application directory to link',
default: '../kibana',
});
const kibanaPath = path.resolve(echDir, appLinkRelativePath);
const kibanaPackageInfo = await getPackageInfo(kibanaPath);

if (kibanaPackageInfo.name !== 'kibana') {
console.log(`
Expected app name to be ${chalk.cyan('kibana')}, found ${chalk.cyan(kibanaPackageInfo.name)}.

to link charts with another application use ${chalk.cyan(
'yarn link',
)} (see https://classic.yarnpkg.com/en/docs/cli/link/)
`);
return;
}

if (linkInfo.path) {
if (linkInfo.path !== kibanaPath) {
console.log(`${chalk.cyan(packageName)} is already linked to ${linkInfo.path}. Please unlink and try again.`);
}

if (isLinked(path.join(kibanaPath, 'node_modules', packageName), echDir)) {
ora(
`Selected ${chalk.cyan(kibanaPackageInfo.name)} application already has ${chalk.cyan(packageName)} link`,
).succeed();
console.log(`
To remove this link run ${chalk.cyan('yarn link:charts')} and select the option to ${chalk.bold.underline(
'Unlink',
)}`);
return;
}
}

console.log(`
Please ensure kibana is bootstrapped and running:
cd ${kibanaPath}

${chalk.dim('# start elasticsearch or configure kibana to point at remote elasticsearch cluster')}
yarn es snapshot --license trial --password changeme -E node.attr.hot_node=true

${chalk.dim('# boostrap and start kibana')}
yarn kbn bootstrap --no-cache
yarn start
`);
await writeLinkInfo(tempDir, {
name: kibanaPackageInfo.name,
path: kibanaPath,
created: new Date(),
});
const { isReady } = await inquirer.prompt({
name: 'isReady',
message: `Press ${chalk.italic('Y')} to continue when kibana is running or ${chalk.italic('N')} to cancel.`,
type: 'confirm',
default: true,
});

if (!isReady) {
console.log('Please ensure kibana is running before linking charts');
return;
}

cps.push(
await spawnWatch(
'yarn build:watch --preserveWatchOutput --pretty --noUnusedLocals false --target ES2018 --noUnusedLocals false ',
packageName,
{
debug,
cwd: echDir,
errorStr: 'error TS',
stopStr: 'Found 0 errors. Watching for file changes',
startStr: 'File change detected. Starting incremental compilation',
onUpdate: () => replaceModules(echDir, kibanaPath, linkedPackages),
},
),
);

// must be run after first build so all assests are visibile to kibana
await linkPackage(echDir, kibanaPath, packageName);

const kbnSharedPackage = path.join(kibanaPath, 'packages/kbn-ui-shared-deps');
cps.push(
await spawnWatch('yarn kbn:watch', '@kbn/ui-shared-dep', {
debug,
cwd: kbnSharedPackage,
errorStr: 'ERROR',
stopStr: 'webpack completed',
startStr: 'Running webpack compilation',
}),
);

await writeLinkInfo(tempDir, {
name: kibanaPackageInfo.name,
path: kibanaPath,
created: new Date(),
});

console.log(`
Link Successful, please keep this tab running to watch for file changes.
Refresh kibana to see all new file changes, each time files are rebuilt.
When finished end this process and run ${chalk.cyan(
'yarn link:charts',
)} and select the option to ${chalk.bold.underline('Unlink')} to cleanup link changes.
`);
} else {
const kibanaPath = linkInfo.path;
if (!kibanaPath) {
ora(`No links found for ${chalk.cyan(packageName)}`).warn();
return;
}

if (action === 'Watch mode') {
cps.push(
await spawnWatch(
'yarn build:watch --preserveWatchOutput --pretty --noUnusedLocals false --target ES2018',
packageName,
{
debug,
cwd: echDir,
errorStr: ': error TS',
stopStr: 'Found 0 errors. Watching for file changes',
startStr: 'File change detected. Starting incremental compilation',
onUpdate: () => replaceModules(echDir, kibanaPath, linkedPackages),
},
),
);

const kbnSharedPackage = path.join(kibanaPath, 'packages/kbn-ui-shared-deps');
cps.push(
await spawnWatch('yarn kbn:watch', '@kbn/ui-shared-dep', {
debug,
cwd: kbnSharedPackage,
errorStr: 'ERROR',
stopStr: 'webpack completed',
startStr: 'Running webpack compilation',
}),
);

return;
}

try {
await exec('yarn build', `Restoring build ${chalk.dim(packageName)}`, {
debug,
cwd: echDir,
errorStr: ': error TS',
});
const chartsFileRestored = await unlinkPackage(linkInfo.path, packageName, debug);

await writeLinkInfo(tempDir, {});

if (chartsFileRestored) {
try {
const kbnSharedPackage = path.join(kibanaPath, 'packages/kbn-ui-shared-deps');
await exec('yarn build --dev', `Restoring build ${chalk.dim('@kbn/ui-shared-dep')}`, {
debug,
errorStr: 'ERROR',
cwd: kbnSharedPackage,
});

console.log(`
Unlink Successful. Kibana has been restored to the pre-linked state.
Please refresh kibana to see restored state.`);
return;
} catch {
// fallthrough
}
}

console.log(`
Unlink Complete. Kibana was ${chalk.underline('not')} restored to the pre-linked state. Please run ${chalk.cyan(
'yarn kbn bootstrap --no-cache',
)}`);
} catch {
console.log(`Unlink Failed. Please fix issues above or run with ${chalk.underline('--debug')} flag.`);
}
}
};
14 changes: 14 additions & 0 deletions packages/link_kibana/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "link-kibana",
"description": "Utility to aid in linking charts to kinana",
"license": "Apache-2.0",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"chalk": "^4.1.1",
"change-case": "^4.1.2",
"glob": "^7.1.7",
"inquirer": "^8.0.0",
"ora": "^5.4.0"
}
}
Loading