Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ build --symlink_prefix=dist/
# Write testing errors to log on test failure
test --test_output=errors

# Do not build runfile forests by default. If an execution strategy relies on runfile
# forests, the forest is created on-demand. See: https://github.com/bazelbuild/bazel/issues/6627
# and https://github.com/bazelbuild/bazel/commit/03246077f948f2790a83520e7dccc2625650e6df. This
# also helps with: https://github.com/bazelbuild/bazel/issues/4327#issuecomment-922106293.
build --nobuild_runfile_links

# Turn on --incompatible_strict_action_env which was on by default
# in Bazel 0.21.0 but turned off again in 0.22.0. Follow
Expand All @@ -47,12 +52,6 @@ build --incompatible_strict_action_env
run --incompatible_strict_action_env
test --incompatible_strict_action_env

# Do not build runfile forests by default. If an execution strategy relies on runfile
# forests, the forest is created on-demand. See: https://github.com/bazelbuild/bazel/issues/6627
# and https://github.com/bazelbuild/bazel/commit/03246077f948f2790a83520e7dccc2625650e6df. This
# also helps with: https://github.com/bazelbuild/bazel/issues/4327#issuecomment-922106293.
build --nobuild_runfile_links

################################
# Remote Execution Setup #
################################
Expand Down
40 changes: 17 additions & 23 deletions bazel/http-server/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
load("//bazel:defaults.bzl", "ts_library")
load("@aspect_rules_js//js:defs.bzl", "js_binary")
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")

package(default_visibility = ["//visibility:public"])

Expand All @@ -11,33 +11,27 @@ filegroup(
srcs = glob(["*"]),
)

ts_library(
ts_project(
name = "server_lib",
srcs = [
"ibazel.ts",
"main.ts",
"server.ts",
"ibazel.mts",
"main.mts",
"server.mts",
],
# A tsconfig needs to be specified as otherwise `ts_library` will look for the config
# in `//:package.json` and this breaks when the BUILD file is copied to `@npm//`.
tsconfig = "//:tsconfig.json",
tsconfig = "//bazel:tsconfig",
deps = [
"@npm//@bazel/runfiles",
"@npm//@types/browser-sync",
"@npm//@types/node",
"@npm//@types/send",
"@npm//@types/yargs",
"@npm//browser-sync",
"@npm//send",
"@npm//yargs",
"//bazel:node_modules/@types/browser-sync",
"//bazel:node_modules/@types/node",
"//bazel:node_modules/@types/send",
"//bazel:node_modules/@types/yargs",
"//bazel:node_modules/browser-sync",
"//bazel:node_modules/send",
"//bazel:node_modules/yargs",
],
)

nodejs_binary(
js_binary(
name = "server_bin",
data = [
":server_lib",
],
entry_point = ":main.ts",
templated_args = ["--nobazel_run_linker"],
data = [":server_lib"],
entry_point = ":main.mjs",
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import {createInterface} from 'readline';
import {HttpServer} from './server';
import {HttpServer} from './server.mjs';

// ibazel will write this string after a successful build.
const ibazelNotifySuccessMessage = 'IBAZEL_BUILD_COMPLETED SUCCESS';
Expand Down
4 changes: 4 additions & 0 deletions bazel/http-server/index.bzl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
load("@aspect_rules_js//js:providers.bzl", "JsInfo")
load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo")

def _get_workspace_name(ctx):
Expand Down Expand Up @@ -29,6 +30,8 @@ def _http_server_rule_impl(ctx):
for dep in ctx.attr.deps:
if JSNamedModuleInfo in dep:
transitive_depsets.append(dep[JSNamedModuleInfo].sources)
if JsInfo in dep:
transitive_depsets.append(dep[JsInfo].transitive_sources)
elif DefaultInfo in dep:
transitive_depsets.append(dep[DefaultInfo].files)

Expand Down Expand Up @@ -136,6 +139,7 @@ http_server_rule = rule(
"_bash_runfile_helpers": attr.label(default = Label("@bazel_tools//tools/bash/runfiles")),
"_server_bin": attr.label(
default = Label("//bazel/http-server:server_bin"),
cfg = "exec",
),
"_launcher_template": attr.label(
allow_single_file = True,
Expand Down
15 changes: 2 additions & 13 deletions bazel/http-server/launcher_template.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,8 @@ source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---

# If we do not run the server as part of a test, we always enforce runfile
# resolution when invoking the server NodeJS binary. This is necessary as
# runfile trees are disabled as part of this repository. The server NodeJS
# binary would not find a relative runfile tree directory and error out.
if [[ -z "${TEST_SRCDIR:-""}" ]]; then
export RUNFILES_MANIFEST_ONLY="1"
fi

# Resolve the path of the server binary. Note: usually we either need to
# resolve the "nodejs_binary" executable with different file extensions on
# windows, but since we already run this launcher as part of a "sh_binary", we
# can safely execute another shell script from the current shell.
serverBin=$(rlocation "devinfra/bazel/http-server/server_bin.sh")
# Resolve the path of the server binary.
serverBin=$(rlocation "devinfra/bazel/http-server/server_bin_/server_bin")

# Start the server with the given arguments. The arguments will be
# substituted based on the rule attributes.
Expand Down
4 changes: 2 additions & 2 deletions bazel/http-server/main.ts → bazel/http-server/main.mts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import yargs from 'yargs';
import assert from 'node:assert';

import {HttpServer} from './server';
import {setupBazelWatcherSupport} from './ibazel';
import {HttpServer} from './server.mjs';
import {setupBazelWatcherSupport} from './ibazel.mjs';

const {
rootPaths,
Expand Down
59 changes: 34 additions & 25 deletions bazel/http-server/server.ts → bazel/http-server/server.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
* found in the LICENSE file at https://angular.io/license
*/

import {readFileSync} from 'fs';
import {runfiles} from '@bazel/runfiles';
import fs from 'node:fs';
import browserSync from 'browser-sync';
import http from 'http';
import path from 'path';
import http from 'node:http';
import path from 'node:path';
import send from 'send';
import assert from 'node:assert';

// The current working directory is the runfiles root.
const runfilesRoot = process.env['RUNFILES_DIR']!;
assert(runfilesRoot, 'Expected `RUNFILES_DIR` to be set.');

/**
* Http Server implementation that uses browser-sync internally. This server
Expand All @@ -26,22 +30,7 @@ export class HttpServer {
server = browserSync.create();

/** Options of the browser-sync server. */
options: browserSync.Options = {
open: false,
online: false,
port: this.port,
notify: false,
ghostMode: false,
server: {
directory: false,
middleware: [
(req, res) => {
this._corsMiddleware(req, res);
this._bazelMiddleware(req, res);
},
],
},
};
options: browserSync.Options;

constructor(
readonly port: number,
Expand All @@ -51,6 +40,23 @@ export class HttpServer {
private _environmentVariables: string[] = [],
private _relaxCors: boolean = false,
) {
this.options = {
open: false,
online: false,
port: this.port,
notify: false,
ghostMode: false,
server: {
directory: false,
middleware: [
(req, res) => {
this._corsMiddleware(req, res);
this._bazelMiddleware(req, res);
},
],
},
};

if (enableUi === false) {
this.options.ui = false;
}
Expand Down Expand Up @@ -131,12 +137,15 @@ export class HttpServer {
return new URL(reqURL, `http://_`).pathname;
}

/** Resolves a given URL from the runfiles using the corresponding manifest path. */
/** Resolves a given URL from the runfiles using a computed manifest path. */
private _resolveUrlFromRunfiles(url: string): string | null {
for (let rootPath of this._rootPaths) {
try {
return runfiles.resolve(path.posix.join(rootPath, getManifestPath(url)));
} catch {}
const fragment = path.posix.join(rootPath, getManifestPath(url));
const diskPath = path.join(runfilesRoot, fragment);

if (fs.existsSync(diskPath)) {
return diskPath;
}
}
return null;
}
Expand All @@ -155,7 +164,7 @@ export class HttpServer {
}

const variables: Record<string, string | undefined> = {};
const content = readFileSync(indexPath, 'utf8');
const content = fs.readFileSync(indexPath, 'utf8');

// Populate variables object that will be inlined.
this._environmentVariables.forEach((name) => (variables[name] = process.env[name]));
Expand Down
27 changes: 13 additions & 14 deletions bazel/http-server/test/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_test")
load("@aspect_rules_js//js:defs.bzl", "js_test")
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
load("//bazel/http-server:index.bzl", "http_server")
load("//tools:defaults.bzl", "ts_library")

ts_library(
ts_project(
name = "app_lib",
testonly = True,
srcs = ["main.ts"],
tsconfig = "tsconfig.app.json",
)

http_server(
Expand All @@ -16,23 +17,21 @@ http_server(
deps = [":app_lib"],
)

ts_library(
ts_project(
name = "test_lib",
testonly = True,
srcs = ["server-test.ts"],
# TODO(devversion): Remove this when `ts_library` supports `.mts` extension.
devmode_module = "commonjs",
tsconfig = "//bazel:tsconfig",
deps = [
"@npm//@bazel/runfiles",
"@npm//@types/node",
"@npm//@types/selenium-webdriver",
"@npm//@types/wait-on",
"@npm//selenium-webdriver",
"@npm//wait-on",
"//bazel:node_modules/@types/node",
"//bazel:node_modules/@types/selenium-webdriver",
"//bazel:node_modules/@types/wait-on",
"//bazel:node_modules/selenium-webdriver",
"//bazel:node_modules/wait-on",
],
)

nodejs_test(
js_test(
name = "test",
# Pass the chromium and chromedriver binaries as arguments to the test.
# These variables are made available by the toolchain alias.
Expand All @@ -45,6 +44,6 @@ nodejs_test(
":test_lib",
"//bazel/browsers/chromium",
],
entry_point = ":server-test.ts",
entry_point = ":server-test.js",
toolchains = ["//bazel/browsers/chromium:toolchain_alias"],
)
16 changes: 11 additions & 5 deletions bazel/http-server/test/server-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/

import {runfiles} from '@bazel/runfiles';
import {Builder, By, WebDriver} from 'selenium-webdriver';
import {Options as ChromeOptions, ServiceBuilder} from 'selenium-webdriver/chrome';

import waitOn from 'wait-on';
import * as childProcess from 'child_process';
import childProcess from 'node:child_process';
import path from 'node:path';

/**
* Test script that will start the test http server binary in a background process.
Expand All @@ -23,9 +23,9 @@ async function runTest() {
const [chromiumRootpath, chromedriverRootpath] = process.argv.slice(2);

// Resolve chromium, chromedriver and the server binary to disk paths.
const chromiumPath = runfiles.resolveWorkspaceRelative(chromiumRootpath);
const chromedriverPath = runfiles.resolveWorkspaceRelative(chromedriverRootpath);
const serverBinPath = runfiles.resolveWorkspaceRelative('bazel/http-server/test/server');
const chromiumPath = path.resolve(chromiumRootpath);
const chromedriverPath = path.resolve(chromedriverRootpath);
const serverBinPath = path.resolve('bazel/http-server/test/server');

const serverPort = 1234;
const serverHost = `127.0.0.1:${serverPort}`;
Expand All @@ -36,6 +36,12 @@ async function runTest() {
stdio: 'inherit',
});

console.error('Spawning');

serverProcess.on('error', (err) => {
console.error(err);
});

// Ensure the process gets killed, if the test terminates early.
process.on('exit', () => serverProcess.kill());

Expand Down
7 changes: 7 additions & 0 deletions bazel/http-server/test/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"strict": true,
"lib": ["dom", "es2022"],
"module": "ES2022"
}
}
12 changes: 11 additions & 1 deletion bazel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@
"name": "@devinfra/bazel",
"dependencies": {
"@microsoft/api-extractor": "7.52.3",
"@types/browser-sync": "2.29.0",
"@types/node": "22.14.0",
"@types/selenium-webdriver": "^4.1.28",
"@types/send": "0.17.4",
"@types/wait-on": "^5.3.4",
"@types/yargs": "17.0.33",
"browser-sync": "3.0.4",
"piscina": "^4.9.2",
"selenium-webdriver": "^4.31.0",
"send": "1.2.0",
"true-case-path": "2.2.1",
"typescript": "5.8.2",
"true-case-path": "2.2.1"
"wait-on": "^8.0.3",
"yargs": "17.7.2"
},
"pnpm": {
"onlyBuiltDependencies": []
Expand Down
Loading
Loading