Skip to content

Commit 86f1684

Browse files
mistickibanamachinetylersmalley
authoredMar 3, 2021
chore(NA): manage npm dependencies within bazel (elastic#92864)
* chore(NA): full WORKSPACE.bazel logic plus manage yarn dependencies with Bazel * chore(NA): update BUILD.bazel files comments on root and packages * chore(NA): add workspace file with useful data * chore(NA): install deps through bazel * chore(NA): update workspace file * chore(NA): update into last rules nodejs * chore(NA): ensure bazel always run yarn install * chore(NA): support offline mode * chore(NA): remove elastic-datemath * chore(NA): restore bazel 4.0.0 * chore(NA): update kbn pm dist * chore(NA): introduce force-install command * docs(NA): update docs with new yarn kbn bootstrap flags * chore(NA): use path.resolve on kbn bootstrap integrity check verification * chore(NA): update .yarnrc Co-authored-by: Tyler Smalley <[email protected]> * chore(NA): change cli argument typo * chore(NA): fix spacing on kbn pm cli Co-authored-by: Kibana Machine <[email protected]> Co-authored-by: Tyler Smalley <[email protected]>
1 parent a8d45e7 commit 86f1684

File tree

13 files changed

+1186
-974
lines changed

13 files changed

+1186
-974
lines changed
 

‎.bazelrc

+9
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,12 @@ build --workspace_status_command="node ./src/dev/bazel_workspace_status.js"
1616
# build --build_metadata=VISIBILITY=PUBLIC
1717
build --build_metadata=TEST_GROUPS=//packages
1818

19+
###############################
20+
# Offline Support #
21+
# Turn on these settings with #
22+
# --config=offline #
23+
###############################
24+
25+
## Reset remote cache and backend support
26+
build:offline --bes_backend="" --remote_cache=""
27+
run:offline --bes_backend="" --remote_cache=""

‎.bazelrc.common

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
# Local Cache Settings
99
## Avoid cache results from being corrupt when changing source during build
10-
common --experimental_guard_against_concurrent_changes
10+
build --experimental_guard_against_concurrent_changes
11+
run --experimental_guard_against_concurrent_changes
12+
test --experimental_guard_against_concurrent_changes
1113

1214
## Cache action outputs on disk so they persist across output_base and bazel shutdown (eg. changing branches)
1315
build --disk_cache=~/.bazel-cache/disk-cache

‎.yarnrc

+6
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@ yarn-offline-mirror ".yarn-local-mirror"
33

44
# Always look into the cache first before fetching online
55
--install.prefer-offline true
6+
7+
# Disable interactive and progress logs as yarn install is now
8+
# managed by Bazel and we are piping the logs from the underlying
9+
# process running bazel into the parent one running kbn
10+
--install.non-interactive true
11+
--install.no-progress true

‎BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Expose those targets as they are required as part of
2+
# other packages builds and need to be included as inputs
13
exports_files(
24
[
35
"tsconfig.json",

‎WORKSPACE.bazel

+66-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,68 @@
1+
# Define the workspace base name and a managed directory by bazel
2+
# that will hold the node_modules called @npm
13
workspace(
2-
name = "kibana",
4+
name = "kibana",
5+
managed_directories = {"@npm": ["node_modules"]},
6+
)
7+
8+
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
9+
10+
# Fetch Node.js rules
11+
http_archive(
12+
name = "build_bazel_rules_nodejs",
13+
sha256 = "bfacf15161d96a6a39510e7b3d3b522cf61cb8b82a31e79400a84c5abcab5347",
14+
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/3.2.1/rules_nodejs-3.2.1.tar.gz"],
15+
)
16+
17+
# Now that we have the rules let's import from them to complete the work
18+
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
19+
20+
# Assure we have at least a given rules_nodejs version
21+
check_rules_nodejs_version(minimum_version_string = "3.2.1")
22+
23+
# Setup the Node.js toolchain for the architectures we want to support
24+
#
25+
# NOTE: darwin-arm64 is not being installed because bazel is not yet available on that architecture.
26+
# The PR for it was merged and should be available in the next release of bazel and bazelisk. As soon as they have it
27+
# we can update that rule.
28+
node_repositories(
29+
node_repositories = {
30+
"14.16.0-darwin_amd64": ("node-v14.16.0-darwin-x64.tar.gz", "node-v14.16.0-darwin-x64", "14ec767e376d1e2e668f997065926c5c0086ec46516d1d45918af8ae05bd4583"),
31+
"14.16.0-linux_arm64": ("node-v14.16.0-linux-arm64.tar.xz", "node-v14.16.0-linux-arm64", "440489a08bfd020e814c9e65017f58d692299ac3f150c8e78d01abb1104c878a"),
32+
"14.16.0-linux_s390x": ("node-v14.16.0-linux-s390x.tar.xz", "node-v14.16.0-linux-s390x", "335348e46f45284b6356416ef58f85602d2dee99094588b65900f6c8839df77e"),
33+
"14.16.0-linux_amd64": ("node-v14.16.0-linux-x64.tar.xz", "node-v14.16.0-linux-x64", "2e079cf638766fedd720d30ec8ffef5d6ceada4e8b441fc2a093cb9a865f4087"),
34+
"14.16.0-windows_amd64": ("node-v14.16.0-win-x64.zip", "node-v14.16.0-win-x64", "716045c2f16ea10ca97bd04cf2e5ef865f9c4d6d677a9bc25e2ea522b594af4f"),
35+
},
36+
node_version = "14.16.0",
37+
node_urls = [
38+
"https://nodejs.org/dist/v{version}/{filename}",
39+
],
40+
yarn_repositories = {
41+
"1.21.1": ("yarn-v1.21.1.tar.gz", "yarn-v1.21.1", "d1d9f4a0f16f5ed484e814afeb98f39b82d4728c6c8beaafb5abc99c02db6674"),
42+
},
43+
yarn_version = "1.21.1",
44+
yarn_urls = [
45+
"https://github.com/yarnpkg/yarn/releases/download/v{version}/{filename}",
46+
],
47+
package_json = ["//:package.json"],
48+
)
49+
50+
# Run yarn_install rule to take care of dependencies
51+
#
52+
# NOTE: FORCE_COLOR env var forces colors on non tty mode
53+
yarn_install(
54+
name = "npm",
55+
environment = {
56+
"FORCE_COLOR": "True",
57+
},
58+
package_json = "//:package.json",
59+
yarn_lock = "//:yarn.lock",
60+
data = [
61+
"//:.yarnrc",
62+
"//:preinstall_check.js",
63+
"//:node_modules/.yarn-integrity",
64+
],
65+
symlink_node_modules = True,
66+
quiet = False,
67+
frozen_lockfile = False,
368
)

‎docs/developer/getting-started/index.asciidoc

+17
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,23 @@ https://github.com/nodejs/node-gyp#installation[https://github.com/nodejs/node-g
4747
and follow the guide according your platform.
4848
____
4949

50+
In case you don't have an internet connection, the `yarn kbn bootstrap` command will
51+
fail. As it is likely you have the required node_modules in the
52+
offline mirror, you can try to run the step in offline mode by using:
53+
54+
[source,bash]
55+
----
56+
yarn kbn bootstrap --offline
57+
----
58+
59+
In any other circumstance where you want to force the node_modules install step
60+
you can use:
61+
62+
[source,bash]
63+
----
64+
yarn kbn bootstrap --force-install
65+
----
66+
5067
(You can also run `yarn kbn` to see the other available commands. For
5168
more info about this tool, see
5269
{kib-repo}tree/{branch}/packages/kbn-pm[{kib-repo}tree/{branch}/packages/kbn-pm].)

‎packages/BUILD.bazel

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# Call each package final target
1+
# Grouping target to call all underlying packages build
2+
# targets so we can build them all at once
23
filegroup(
34
name = "build",
45
srcs = [],

‎packages/kbn-pm/dist/index.js

+1,012-955
Large diffs are not rendered by default.

‎packages/kbn-pm/src/cli.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ function help() {
3737
--skip-kibana-plugins Filter all plugins in ./plugins and ../kibana-extra when running command.
3838
--no-cache Disable the kbn packages bootstrap cache
3939
--no-validate Disable the bootstrap yarn.lock validation
40+
--force-install Forces yarn install to run on bootstrap
41+
--offline Run in offline mode
4042
--verbose Set log level to verbose
4143
--debug Set log level to debug
4244
--quiet Set log level to error
@@ -73,9 +75,11 @@ export async function run(argv: string[]) {
7375
},
7476
default: {
7577
cache: true,
78+
'force-install': true,
79+
offline: false,
7680
validate: true,
7781
},
78-
boolean: ['cache', 'validate'],
82+
boolean: ['cache', 'force-install', 'offline', 'validate'],
7983
});
8084

8185
const args = options._;

‎packages/kbn-pm/src/commands/bootstrap.ts

+36-14
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Side Public License, v 1.
77
*/
88

9-
import { sep } from 'path';
9+
import { resolve, sep } from 'path';
1010
import { linkProjectExecutables } from '../utils/link_project_executables';
1111
import { log } from '../utils/log';
1212
import { parallelizeBatches } from '../utils/parallelize';
@@ -17,7 +17,7 @@ import { getAllChecksums } from '../utils/project_checksums';
1717
import { BootstrapCacheFile } from '../utils/bootstrap_cache_file';
1818
import { readYarnLock } from '../utils/yarn_lock';
1919
import { validateDependencies } from '../utils/validate_dependencies';
20-
import { installBazelTools, runBazel } from '../utils/bazel';
20+
import { ensureYarnIntegrityFileExists, installBazelTools, runBazel } from '../utils/bazel';
2121

2222
export const BootstrapCommand: ICommand = {
2323
description: 'Install dependencies and crosslink projects',
@@ -26,12 +26,36 @@ export const BootstrapCommand: ICommand = {
2626
async run(projects, projectGraph, { options, kbn, rootPath }) {
2727
const nonBazelProjectsOnly = await getNonBazelProjectsOnly(projects);
2828
const batchedNonBazelProjects = topologicallyBatchProjects(nonBazelProjectsOnly, projectGraph);
29-
const kibanaProjectPath = projects.get('kibana')?.path;
29+
const kibanaProjectPath = projects.get('kibana')?.path || '';
30+
const runOffline = options?.offline === true;
31+
const forceInstall = !!options && options['force-install'] === true;
32+
33+
// Ensure we have a `node_modules/.yarn-integrity` file as we depend on it
34+
// for bazel to know it has to re-install the node_modules after a reset or a clean
35+
await ensureYarnIntegrityFileExists(resolve(kibanaProjectPath, 'node_modules'));
3036

3137
// Install bazel machinery tools if needed
3238
await installBazelTools(rootPath);
3339

34-
// Install monorepo npm dependencies
40+
// Bootstrap process for Bazel packages
41+
// Bazel is now managing dependencies so yarn install
42+
// will happen as part of this
43+
//
44+
// NOTE: Bazel projects will be introduced incrementally
45+
// And should begin from the ones with none dependencies forward.
46+
// That way non bazel projects could depend on bazel projects but not the other way around
47+
// That is only intended during the migration process while non Bazel projects are not removed at all.
48+
//
49+
// Until we have our first package build within Bazel we will always need to directly call the yarn rule
50+
// otherwise yarn install won't trigger as we don't have any npm dependency within Bazel
51+
// TODO: Change CLI default in order to not force install as soon as we have our first Bazel package being built
52+
if (forceInstall) {
53+
await runBazel(['run', '@nodejs//:yarn'], runOffline);
54+
}
55+
56+
await runBazel(['build', '//packages:build'], runOffline);
57+
58+
// Install monorepo npm dependencies outside of the Bazel managed ones
3559
for (const batch of batchedNonBazelProjects) {
3660
for (const project of batch) {
3761
const isExternalPlugin = project.path.includes(`${kibanaProjectPath}${sep}plugins`);
@@ -40,12 +64,16 @@ export const BootstrapCommand: ICommand = {
4064
continue;
4165
}
4266

43-
if (project.isSinglePackageJsonProject || isExternalPlugin) {
67+
if (isExternalPlugin) {
4468
await project.installDependencies();
4569
continue;
4670
}
4771

48-
if (!project.isEveryDependencyLocal() && !isExternalPlugin) {
72+
if (
73+
!project.isSinglePackageJsonProject &&
74+
!project.isEveryDependencyLocal() &&
75+
!isExternalPlugin
76+
) {
4977
throw new Error(
5078
`[${project.name}] is not eligible to hold non local dependencies. Move the non local dependencies into the top level package.json.`
5179
);
@@ -61,15 +89,9 @@ export const BootstrapCommand: ICommand = {
6189

6290
// Assure all kbn projects with bin defined scripts
6391
// copy those scripts into the top level node_modules folder
64-
await linkProjectExecutables(projects, projectGraph);
65-
66-
// Bootstrap process for Bazel packages
6792
//
68-
// NOTE: Bazel projects will be introduced incrementally
69-
// And should begin from the ones with none dependencies forward.
70-
// That way non bazel projects could depend on bazel projects but not the other way around
71-
// That is only intended during the migration process while non Bazel projects are not removed at all.
72-
await runBazel(['build', '//packages:build']);
93+
// NOTE: We don't probably need this anymore, is actually not being used
94+
await linkProjectExecutables(projects, projectGraph);
7395

7496
// Bootstrap process for non Bazel packages
7597
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
import { join } from 'path';
10+
import { writeFile } from '../fs';
11+
12+
export async function ensureYarnIntegrityFileExists(nodeModulesPath: string) {
13+
try {
14+
await writeFile(join(nodeModulesPath, '.yarn-integrity'), '', { flag: 'wx' });
15+
} catch {
16+
// no-op
17+
}
18+
}

‎packages/kbn-pm/src/utils/bazel/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Side Public License, v 1.
77
*/
88

9+
export * from './ensure_yarn_integrity_exists';
910
export * from './get_cache_folders';
1011
export * from './install_tools';
1112
export * from './run';

‎packages/kbn-pm/src/utils/bazel/run.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,21 @@ import { observeLines } from '@kbn/dev-utils/stdio';
1414
import { spawn } from '../child_process';
1515
import { log } from '../log';
1616

17-
export async function runBazel(bazelArgs: string[], runOpts: execa.Options = {}) {
17+
export async function runBazel(
18+
bazelArgs: string[],
19+
offline: boolean = false,
20+
runOpts: execa.Options = {}
21+
) {
1822
// Force logs to pipe in order to control the output of them
1923
const bazelOpts: execa.Options = {
2024
...runOpts,
2125
stdio: 'pipe',
2226
};
2327

28+
if (offline) {
29+
bazelArgs.push('--config=offline');
30+
}
31+
2432
const bazelProc = spawn('bazel', bazelArgs, bazelOpts);
2533

2634
const bazelLogs$ = new Rx.Subject<string>();

0 commit comments

Comments
 (0)
Please sign in to comment.