Skip to content

Commit

Permalink
[kbn/pm] allow packages to define extra paths to clean (#26132)
Browse files Browse the repository at this point in the history
I noticed some discussion about how kbn clean should probably clear out the `.eslintcache` file, since it doesn't handle changes in related modules (for things like the import plugin) and it would be nice if `yarn kbn clean` took care of the issue. I figured it's not a bad idea, but adding `.eslintcache` directly to `@kbn/pm` felt wrong, so instead I've added another config options that can go in the package.json file, `clean.extraPatterns`. This array of patterns is passed into `del()` so that it can include things like negation.

As the name suggests this doesn't override the initial paths, just adds some extras that will be checked and cleared when `yarn kbn clean` is run.
  • Loading branch information
Spencer committed Nov 27, 2018
1 parent 34d7a3b commit c6ce1a6
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 36 deletions.
9 changes: 9 additions & 0 deletions package.json
Expand Up @@ -22,6 +22,15 @@
"bugs": {
"url": "http://github.com/elastic/kibana/issues"
},
"kibana": {
"clean": {
"extraPatterns": [
"build",
"optimize",
".eslintcache"
]
}
},
"author": "Rashid Khan <rashid.khan@elastic.co>",
"scripts": {
"preinstall": "node ./preinstall_check",
Expand Down
48 changes: 34 additions & 14 deletions packages/kbn-pm/dist/index.js
Expand Up @@ -7845,7 +7845,6 @@ class Project {
this.path = projectPath;
this.packageJsonLocation = (0, _path.resolve)(this.path, 'package.json');
this.nodeModulesLocation = (0, _path.resolve)(this.path, 'node_modules');
this.optimizeLocation = (0, _path.resolve)(this.path, 'optimize');
this.targetLocation = (0, _path.resolve)(this.path, 'target');
this.productionDependencies = this.json.dependencies || {};
this.devDependencies = this.json.devDependencies || {};
Expand Down Expand Up @@ -7900,6 +7899,9 @@ class Project {
getIntermediateBuildDirectory() {
return (0, _path.resolve)(this.path, this.getBuildConfig().intermediateBuildDirectory || '.');
}
getCleanConfig() {
return this.json.kibana && this.json.kibana.clean || {};
}
hasScript(name) {
return name in this.scripts;
}
Expand Down Expand Up @@ -23153,28 +23155,46 @@ function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, a
const CleanCommand = exports.CleanCommand = {
description: 'Remove the node_modules and target directories from all projects.',
name: 'clean',
run(projects, projectGraph, { rootPath }) {
run(projects) {
return _asyncToGenerator(function* () {
const directoriesToDelete = [];
const toDelete = [];
for (const project of projects.values()) {
if (yield (0, _fs.isDirectory)(project.nodeModulesLocation)) {
directoriesToDelete.push(project.nodeModulesLocation);
toDelete.push({
cwd: project.path,
pattern: (0, _path.relative)(project.path, project.nodeModulesLocation)
});
}
if (yield (0, _fs.isDirectory)(project.targetLocation)) {
directoriesToDelete.push(project.targetLocation);
toDelete.push({
cwd: project.path,
pattern: (0, _path.relative)(project.path, project.targetLocation)
});
}
if (yield (0, _fs.isDirectory)(project.optimizeLocation)) {
directoriesToDelete.push(project.optimizeLocation);
const { extraPatterns } = project.getCleanConfig();
if (extraPatterns) {
toDelete.push({
cwd: project.path,
pattern: extraPatterns
});
}
}
if (directoriesToDelete.length === 0) {
_log.log.write(_chalk2.default.bold.green('\n\nNo directories to delete'));
if (toDelete.length === 0) {
_log.log.write(_chalk2.default.bold.green('\n\nNothing to delete'));
} else {
_log.log.write(_chalk2.default.bold.red('\n\nDeleting directories:\n'));
for (const dir of directoriesToDelete) {
const deleting = (0, _del2.default)(dir, { force: true });
_ora2.default.promise(deleting, (0, _path.relative)(rootPath, dir));
yield deleting;
_log.log.write(_chalk2.default.bold.red('\n\nDeleting:\n'));
const originalCwd = process.cwd();
try {
for (const _ref of toDelete) {
const { pattern, cwd } = _ref;

process.chdir(cwd);
const promise = (0, _del2.default)(pattern);
_ora2.default.promise(promise, (0, _path.relative)(originalCwd, (0, _path.join)(cwd, String(pattern))));
yield promise;
}
} finally {
process.chdir(originalCwd);
}
}
})();
Expand Down
Expand Up @@ -24,7 +24,6 @@ Array [
},
},
"nodeModulesLocation": "<repoRoot>/packages/kbn-pm/src/commands/node_modules",
"optimizeLocation": "<repoRoot>/packages/kbn-pm/src/commands/optimize",
"packageJsonLocation": "<repoRoot>/packages/kbn-pm/src/commands/package.json",
"path": "<repoRoot>/packages/kbn-pm/src/commands",
"productionDependencies": Object {
Expand All @@ -46,7 +45,6 @@ Array [
"version": "1.0.0",
},
"nodeModulesLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/node_modules",
"optimizeLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/optimize",
"packageJsonLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/package.json",
"path": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar",
"productionDependencies": Object {},
Expand All @@ -71,7 +69,6 @@ Array [
"version": "1.0.0",
},
"nodeModulesLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/node_modules",
"optimizeLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/optimize",
"packageJsonLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/package.json",
"path": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar",
"productionDependencies": Object {},
Expand Down Expand Up @@ -105,7 +102,6 @@ Array [
"version": "1.0.0",
},
"nodeModulesLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/node_modules",
"optimizeLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/optimize",
"packageJsonLocation": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar/package.json",
"path": "<repoRoot>/packages/kbn-pm/src/commands/packages/bar",
"productionDependencies": Object {},
Expand Down
53 changes: 39 additions & 14 deletions packages/kbn-pm/src/commands/clean.ts
Expand Up @@ -20,7 +20,7 @@
import chalk from 'chalk';
import del from 'del';
import ora from 'ora';
import { relative } from 'path';
import { join, relative } from 'path';

import { isDirectory } from '../utils/fs';
import { log } from '../utils/log';
Expand All @@ -30,31 +30,56 @@ export const CleanCommand: ICommand = {
description: 'Remove the node_modules and target directories from all projects.',
name: 'clean',

async run(projects, projectGraph, { rootPath }) {
const directoriesToDelete = [];
async run(projects) {
const toDelete = [];
for (const project of projects.values()) {
if (await isDirectory(project.nodeModulesLocation)) {
directoriesToDelete.push(project.nodeModulesLocation);
toDelete.push({
cwd: project.path,
pattern: relative(project.path, project.nodeModulesLocation),
});
}

if (await isDirectory(project.targetLocation)) {
directoriesToDelete.push(project.targetLocation);
toDelete.push({
cwd: project.path,
pattern: relative(project.path, project.targetLocation),
});
}

if (await isDirectory(project.optimizeLocation)) {
directoriesToDelete.push(project.optimizeLocation);
const { extraPatterns } = project.getCleanConfig();
if (extraPatterns) {
toDelete.push({
cwd: project.path,
pattern: extraPatterns,
});
}
}

if (directoriesToDelete.length === 0) {
log.write(chalk.bold.green('\n\nNo directories to delete'));
if (toDelete.length === 0) {
log.write(chalk.bold.green('\n\nNothing to delete'));
} else {
log.write(chalk.bold.red('\n\nDeleting directories:\n'));
log.write(chalk.bold.red('\n\nDeleting:\n'));

for (const dir of directoriesToDelete) {
const deleting = del(dir, { force: true });
ora.promise(deleting, relative(rootPath, dir));
await deleting;
/**
* In order to avoid patterns like `/build` in packages from accidentally
* impacting files outside the package we use `process.chdir()` to change
* the cwd to the package and execute `del()` without the `force` option
* so it will check that each file being deleted is within the package.
*
* `del()` does support a `cwd` option, but it's only for resolving the
* patterns and does not impact the cwd check.
*/
const originalCwd = process.cwd();
try {
for (const { pattern, cwd } of toDelete) {
process.chdir(cwd);
const promise = del(pattern);
ora.promise(promise, relative(originalCwd, join(cwd, String(pattern))));
await promise;
}
} finally {
process.chdir(originalCwd);
}
}
},
Expand Down
14 changes: 10 additions & 4 deletions packages/kbn-pm/src/utils/project.ts
Expand Up @@ -32,11 +32,15 @@ import {
} from './package_json';
import { installInDir, runScriptInPackage, runScriptInPackageStreaming } from './scripts';

interface IBuildConfig {
interface BuildConfig {
skip?: boolean;
intermediateBuildDirectory?: string;
}

interface CleanConfig {
extraPatterns?: string[];
}

export class Project {
public static async fromPath(path: string) {
const pkgJson = await readPackageJson(path);
Expand All @@ -46,7 +50,6 @@ export class Project {
public readonly json: IPackageJson;
public readonly packageJsonLocation: string;
public readonly nodeModulesLocation: string;
public readonly optimizeLocation: string;
public readonly targetLocation: string;
public readonly path: string;
public readonly allDependencies: IPackageDependencies;
Expand All @@ -62,7 +65,6 @@ export class Project {

this.packageJsonLocation = resolvePath(this.path, 'package.json');
this.nodeModulesLocation = resolvePath(this.path, 'node_modules');
this.optimizeLocation = resolvePath(this.path, 'optimize');
this.targetLocation = resolvePath(this.path, 'target');

this.productionDependencies = this.json.dependencies || {};
Expand Down Expand Up @@ -117,7 +119,7 @@ export class Project {
);
}

public getBuildConfig(): IBuildConfig {
public getBuildConfig(): BuildConfig {
return (this.json.kibana && this.json.kibana.build) || {};
}

Expand All @@ -130,6 +132,10 @@ export class Project {
return resolvePath(this.path, this.getBuildConfig().intermediateBuildDirectory || '.');
}

public getCleanConfig(): CleanConfig {
return (this.json.kibana && this.json.kibana.clean) || {};
}

public hasScript(name: string) {
return name in this.scripts;
}
Expand Down

0 comments on commit c6ce1a6

Please sign in to comment.