mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[kbn-pm] Enable intermediate build directory for projects (#16839)
This commit is contained in:
parent
7b9a8e0557
commit
8de986040f
12 changed files with 243 additions and 32 deletions
54
packages/kbn-pm/dist/index.js
vendored
54
packages/kbn-pm/dist/index.js
vendored
|
@ -6787,14 +6787,10 @@ var _writePkg = __webpack_require__(290);
|
|||
|
||||
var _writePkg2 = _interopRequireDefault(_writePkg);
|
||||
|
||||
var _path = __webpack_require__(1);
|
||||
|
||||
var _path2 = _interopRequireDefault(_path);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function readPackageJson(dir) {
|
||||
return (0, _readPkg2.default)(_path2.default.join(dir, 'package.json'), { normalize: false });
|
||||
return (0, _readPkg2.default)(dir, { normalize: false });
|
||||
}
|
||||
function writePackageJson(path, json) {
|
||||
return (0, _writePkg2.default)(path, json);
|
||||
|
@ -9642,9 +9638,22 @@ class Project {
|
|||
}
|
||||
throw new _errors.CliError(`[${this.name}] depends on [${project.name}], but it's not using the local package. ${updateMsg}`, meta);
|
||||
}
|
||||
getBuildConfig() {
|
||||
return this.json.kibana && this.json.kibana.build || {};
|
||||
}
|
||||
/**
|
||||
* Whether a package should not be included in the Kibana build artifact.
|
||||
*/
|
||||
skipFromBuild() {
|
||||
const json = this.json;
|
||||
return json.kibana && json.kibana.build && json.kibana.build.skip === true;
|
||||
return this.getBuildConfig().skip === true;
|
||||
}
|
||||
/**
|
||||
* Returns the directory that should be copied into the Kibana build artifact.
|
||||
* This config can be specified to only include the project's build artifacts
|
||||
* instead of everything located in the project directory.
|
||||
*/
|
||||
getIntermediateBuildDirectory() {
|
||||
return _path2.default.resolve(this.path, this.getBuildConfig().intermediateBuildDirectory || '.');
|
||||
}
|
||||
hasScript(name) {
|
||||
return name in this.scripts;
|
||||
|
@ -40994,25 +41003,38 @@ let buildProject = (() => {
|
|||
return _ref4.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
/**
|
||||
* Copy all the project's files from its "intermediate build directory" and
|
||||
* into the build. The intermediate directory can either be the root of the
|
||||
* project or some other location defined in the project's `package.json`.
|
||||
*
|
||||
* When copying all the files into the build, we exclude `node_modules` because
|
||||
* we want the Kibana build to be responsible for actually installing all
|
||||
* dependencies. The primary reason for allowing the Kibana build process to
|
||||
* manage dependencies is that it will "dedupe" them, so we don't include
|
||||
* unnecessary copies of dependencies.
|
||||
*/
|
||||
|
||||
|
||||
let copyToBuild = (() => {
|
||||
var _ref5 = _asyncToGenerator(function* (project, kibanaRoot, buildRoot) {
|
||||
// We want the package to have the same relative location within the build
|
||||
const relativeProjectPath = (0, _path.relative)(kibanaRoot, project.path);
|
||||
const buildProjectPath = (0, _path.resolve)(buildRoot, relativeProjectPath);
|
||||
// When copying all the files into the build, we exclude `package.json` as we
|
||||
// write a separate "production-ready" `package.json` below, and we exclude
|
||||
// `node_modules` because we want the Kibana build to actually install all
|
||||
// dependencies. The primary reason for allowing the Kibana build process to
|
||||
// install the dependencies is that it will "dedupe" them, so we don't include
|
||||
// unnecessary copies of dependencies.
|
||||
yield (0, _cpy2.default)(['**/*', '!package.json', '!node_modules/**'], buildProjectPath, {
|
||||
cwd: project.path,
|
||||
yield (0, _cpy2.default)(['**/*', '!node_modules/**'], buildProjectPath, {
|
||||
cwd: project.getIntermediateBuildDirectory(),
|
||||
parents: true,
|
||||
nodir: true,
|
||||
dot: true
|
||||
});
|
||||
const packageJson = project.json;
|
||||
// If a project is using an intermediate build directory, we special-case our
|
||||
// handling of `package.json`, as the project build process might have copied
|
||||
// (a potentially modified) `package.json` into the intermediate build
|
||||
// directory already. If so, we want to use that `package.json` as the basis
|
||||
// for creating the production-ready `package.json`. If it's not present in
|
||||
// the intermediate build, we fall back to using the project's already defined
|
||||
// `package.json`.
|
||||
const packageJson = (yield (0, _fs.isFile)((0, _path.join)(buildProjectPath, 'package.json'))) ? yield (0, _package_json.readPackageJson)(buildProjectPath) : project.json;
|
||||
const preparedPackageJson = (0, _package_json.createProductionPackageJson)(packageJson);
|
||||
yield (0, _package_json.writePackageJson)(buildProjectPath, preparedPackageJson);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import del from 'del';
|
||||
import { relative, resolve } from 'path';
|
||||
import { relative, resolve, join } from 'path';
|
||||
import copy from 'cpy';
|
||||
|
||||
import { getProjectPaths } from '../config';
|
||||
|
@ -11,8 +11,9 @@ import {
|
|||
import {
|
||||
createProductionPackageJson,
|
||||
writePackageJson,
|
||||
readPackageJson,
|
||||
} from '../utils/package_json';
|
||||
import { isDirectory } from '../utils/fs';
|
||||
import { isDirectory, isFile } from '../utils/fs';
|
||||
import { Project } from '../utils/project';
|
||||
|
||||
export async function buildProductionProjects({
|
||||
|
@ -76,6 +77,17 @@ async function buildProject(project: Project) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all the project's files from its "intermediate build directory" and
|
||||
* into the build. The intermediate directory can either be the root of the
|
||||
* project or some other location defined in the project's `package.json`.
|
||||
*
|
||||
* When copying all the files into the build, we exclude `node_modules` because
|
||||
* we want the Kibana build to be responsible for actually installing all
|
||||
* dependencies. The primary reason for allowing the Kibana build process to
|
||||
* manage dependencies is that it will "dedupe" them, so we don't include
|
||||
* unnecessary copies of dependencies.
|
||||
*/
|
||||
async function copyToBuild(
|
||||
project: Project,
|
||||
kibanaRoot: string,
|
||||
|
@ -85,20 +97,24 @@ async function copyToBuild(
|
|||
const relativeProjectPath = relative(kibanaRoot, project.path);
|
||||
const buildProjectPath = resolve(buildRoot, relativeProjectPath);
|
||||
|
||||
// When copying all the files into the build, we exclude `package.json` as we
|
||||
// write a separate "production-ready" `package.json` below, and we exclude
|
||||
// `node_modules` because we want the Kibana build to actually install all
|
||||
// dependencies. The primary reason for allowing the Kibana build process to
|
||||
// install the dependencies is that it will "dedupe" them, so we don't include
|
||||
// unnecessary copies of dependencies.
|
||||
await copy(['**/*', '!package.json', '!node_modules/**'], buildProjectPath, {
|
||||
cwd: project.path,
|
||||
await copy(['**/*', '!node_modules/**'], buildProjectPath, {
|
||||
cwd: project.getIntermediateBuildDirectory(),
|
||||
parents: true,
|
||||
nodir: true,
|
||||
dot: true,
|
||||
});
|
||||
|
||||
const packageJson = project.json;
|
||||
// If a project is using an intermediate build directory, we special-case our
|
||||
// handling of `package.json`, as the project build process might have copied
|
||||
// (a potentially modified) `package.json` into the intermediate build
|
||||
// directory already. If so, we want to use that `package.json` as the basis
|
||||
// for creating the production-ready `package.json`. If it's not present in
|
||||
// the intermediate build, we fall back to using the project's already defined
|
||||
// `package.json`.
|
||||
const packageJson = (await isFile(join(buildProjectPath, 'package.json')))
|
||||
? await readPackageJson(buildProjectPath)
|
||||
: project.json;
|
||||
|
||||
const preparedPackageJson = createProductionPackageJson(packageJson);
|
||||
await writePackageJson(buildProjectPath, preparedPackageJson);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "@elastic/baz",
|
||||
"version": "1.0.0",
|
||||
"main": "./index.js"
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
console.log('@elastic/baz');
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "@elastic/baz",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"main": "./code.js",
|
||||
"dependencies": {
|
||||
"noop3": "999.999.999"
|
||||
},
|
||||
"devDependencies": {
|
||||
"shx": "^0.2.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "shx cp code.js build/index.js"
|
||||
},
|
||||
"kibana": {
|
||||
"build": {
|
||||
"intermediateBuildDirectory": "build"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@elastic/quux",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"main": "./quux.js",
|
||||
"devDependencies": {
|
||||
"shx": "^0.2.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "shx mkdir build; shx cp quux.js build/index.js"
|
||||
},
|
||||
"kibana": {
|
||||
"build": {
|
||||
"intermediateBuildDirectory": "build"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
console.log('@elastic/quux');
|
|
@ -6,9 +6,81 @@ Array [
|
|||
"packages/bar/src/index.js",
|
||||
"packages/bar/target/index.js",
|
||||
"packages/bar/yarn.lock",
|
||||
"packages/baz/index.js",
|
||||
"packages/baz/package.json",
|
||||
"packages/foo/package.json",
|
||||
"packages/foo/src/index.js",
|
||||
"packages/foo/target/index.js",
|
||||
"packages/foo/yarn.lock",
|
||||
"packages/quux/index.js",
|
||||
"packages/quux/package.json",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`kbn-pm production builds and copies projects for production: packages/bar/package.json 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {
|
||||
"lodash": "4.17.4",
|
||||
},
|
||||
"devDependencies": Object {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
},
|
||||
"main": "./target/index.js",
|
||||
"name": "@elastic/bar",
|
||||
"private": true,
|
||||
"scripts": Object {
|
||||
"build": "babel --presets env --out-dir target src",
|
||||
},
|
||||
"version": "1.0.0",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`kbn-pm production builds and copies projects for production: packages/baz/package.json 1`] = `
|
||||
Object {
|
||||
"main": "./index.js",
|
||||
"name": "@elastic/baz",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`kbn-pm production builds and copies projects for production: packages/foo/package.json 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {
|
||||
"@elastic/bar": "file:../bar",
|
||||
"lodash": "4.17.4",
|
||||
},
|
||||
"devDependencies": Object {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"moment": "2.20.1",
|
||||
},
|
||||
"main": "./target/index.js",
|
||||
"name": "@elastic/foo",
|
||||
"private": true,
|
||||
"scripts": Object {
|
||||
"build": "babel --presets env --out-dir target src",
|
||||
},
|
||||
"version": "1.0.0",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`kbn-pm production builds and copies projects for production: packages/quux/package.json 1`] = `
|
||||
Object {
|
||||
"devDependencies": Object {
|
||||
"shx": "^0.2.2",
|
||||
},
|
||||
"kibana": Object {
|
||||
"build": Object {
|
||||
"intermediateBuildDirectory": "build",
|
||||
},
|
||||
},
|
||||
"main": "./quux.js",
|
||||
"name": "@elastic/quux",
|
||||
"private": true,
|
||||
"scripts": Object {
|
||||
"build": "shx mkdir build; shx cp quux.js build/index.js",
|
||||
},
|
||||
"version": "1.0.0",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import tempy from 'tempy';
|
||||
import copy from 'cpy';
|
||||
import { resolve } from 'path';
|
||||
import { resolve, relative, join } from 'path';
|
||||
import globby from 'globby';
|
||||
|
||||
import { buildProductionProjects } from '../build_production_projects';
|
||||
import { getProjects } from '../../utils/projects';
|
||||
import { readPackageJson } from '../../utils/package_json';
|
||||
|
||||
describe('kbn-pm production', function() {
|
||||
test(
|
||||
|
@ -38,7 +39,15 @@ describe('kbn-pm production', function() {
|
|||
});
|
||||
|
||||
expect(files.sort()).toMatchSnapshot();
|
||||
|
||||
for (const file of files) {
|
||||
if (file.endsWith('package.json')) {
|
||||
expect(await readPackageJson(join(buildRoot, file))).toMatchSnapshot(
|
||||
file
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
60 * 1000
|
||||
2 * 60 * 1000
|
||||
);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ export type PackageDependencies = { [key: string]: string };
|
|||
export type PackageScripts = { [key: string]: string };
|
||||
|
||||
export function readPackageJson(dir: string) {
|
||||
return readPkg(path.join(dir, 'package.json'), { normalize: false });
|
||||
return readPkg(dir, { normalize: false });
|
||||
}
|
||||
|
||||
export function writePackageJson(path: string, json: PackageJson) {
|
||||
|
|
|
@ -143,3 +143,28 @@ describe('#getExecutables()', () => {
|
|||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getIntermediateBuildDirectory', () => {
|
||||
test('is the same as the project path when not specified', () => {
|
||||
const project = createProjectWith({}, 'packages/my-project');
|
||||
const path = project.getIntermediateBuildDirectory();
|
||||
|
||||
expect(path).toBe(project.path);
|
||||
});
|
||||
|
||||
test('appends the `intermediateBuildDirectory` to project path when specified', () => {
|
||||
const project = createProjectWith(
|
||||
{
|
||||
kibana: {
|
||||
build: {
|
||||
intermediateBuildDirectory: 'quux',
|
||||
},
|
||||
},
|
||||
},
|
||||
'packages/my-project'
|
||||
);
|
||||
const path = project.getIntermediateBuildDirectory();
|
||||
|
||||
expect(path).toBe(join(project.path, 'quux'));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,6 +16,11 @@ import {
|
|||
} from './package_json';
|
||||
import { CliError } from './errors';
|
||||
|
||||
interface BuildConfig {
|
||||
skip?: boolean;
|
||||
intermediateBuildDirectory?: string;
|
||||
}
|
||||
|
||||
export class Project {
|
||||
static async fromPath(path: string) {
|
||||
const pkgJson = await readPackageJson(path);
|
||||
|
@ -86,9 +91,27 @@ export class Project {
|
|||
);
|
||||
}
|
||||
|
||||
getBuildConfig(): BuildConfig {
|
||||
return (this.json.kibana && this.json.kibana.build) || {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a package should not be included in the Kibana build artifact.
|
||||
*/
|
||||
skipFromBuild() {
|
||||
const json = this.json;
|
||||
return json.kibana && json.kibana.build && json.kibana.build.skip === true;
|
||||
return this.getBuildConfig().skip === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory that should be copied into the Kibana build artifact.
|
||||
* This config can be specified to only include the project's build artifacts
|
||||
* instead of everything located in the project directory.
|
||||
*/
|
||||
getIntermediateBuildDirectory() {
|
||||
return path.resolve(
|
||||
this.path,
|
||||
this.getBuildConfig().intermediateBuildDirectory || '.'
|
||||
);
|
||||
}
|
||||
|
||||
hasScript(name: string) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue