SERVER-102340 Add a bazel test target for jscore (#34758)

Co-authored-by: Steve McClure <steve.mcclure@mongodb.com>
GitOrigin-RevId: 4a0e650ee88111796615d5e1d4a41870a805b3ec
This commit is contained in:
Sean Lyons 2025-04-09 18:59:34 -04:00 committed by MongoDB Bot
parent 296b89dcf4
commit 9c712cf261
16 changed files with 478 additions and 3 deletions

3
.github/CODEOWNERS vendored
View File

@ -29,6 +29,9 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
# The following patterns are parsed from ./bazel/OWNERS.yml
/bazel/**/* @10gen/devprod-build @svc-auto-approve-bot
# The following patterns are parsed from ./bazel/resmoke/OWNERS.yml
/bazel/resmoke/**/* @10gen/devprod-correctness @svc-auto-approve-bot
# The following patterns are parsed from ./buildfarm/OWNERS.yml
/buildfarm/**/* @10gen/devprod-build @svc-auto-approve-bot

View File

@ -381,3 +381,10 @@ mongo_install(
"//src/mongo/db/query/search/mongotmock",
],
)
filegroup(
name = "installed-dist-test",
srcs = glob([
"dist-test/**",
]),
)

35
bazel/resmoke/BUILD.bazel Normal file
View File

@ -0,0 +1,35 @@
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
genrule(
name = "resmoke_mongo_version",
srcs = [],
outs = [".resmoke_mongo_version.yml"],
cmd = """
echo mongo_version: $(MONGO_VERSION) > $@
""",
visibility = ["//visibility:public"],
)
genrule(
name = "off_feature_flags",
srcs = [],
outs = ["off_feature_flags.txt"],
cmd = """
grep ^off_feature_flags bazel-out/volatile-status.txt | cut -d' ' -f2- | tr ' ' '\n' > $@
""",
stamp = True,
tags = ["external"], # Consuming the feature flag information from volatile-status, so this should always execute.
visibility = ["//visibility:public"],
)
bool_flag(
name = "in_evergreen",
build_setting_default = False,
)
config_setting(
name = "in_evergreen_enabled",
flag_values = {
"//bazel/resmoke:in_evergreen": "True",
},
)

5
bazel/resmoke/OWNERS.yml Normal file
View File

@ -0,0 +1,5 @@
version: 1.0.0
filters:
- "*":
approvers:
- 10gen/devprod-correctness

View File

@ -0,0 +1,16 @@
import pathlib
import sys
REPO_ROOT = pathlib.Path(__file__).parent.parent.parent
sys.path.append(str(REPO_ROOT))
from buildscripts.idl.gen_all_feature_flag_list import get_all_feature_flags_turned_off_by_default
def main():
off_ff = get_all_feature_flags_turned_off_by_default()
print(" ".join(off_ff))
if __name__ == "__main__":
main()

133
bazel/resmoke/resmoke.bzl Normal file
View File

@ -0,0 +1,133 @@
load("//bazel/install_rules:install_rules.bzl", "MongoInstallInfo")
def get_from_volatile_status(ctx, key):
return "`grep '^" + key + " ' " + ctx.version_file.short_path + " | cut -d' ' -f2`"
def _resmoke_suite_test_impl(ctx):
python = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"].py3_runtime
python_path = []
for path in ctx.attr.resmoke[PyInfo].imports.to_list():
if path not in python_path:
python_path.append("$TEST_SRCDIR/" + path)
python_path = ctx.configuration.host_path_separator.join(python_path)
# Put install binaries on the path for resmoke. The MongoInstallInfo has each binary in its own
# directory.
binary_path = []
for data in ctx.attr.data:
if MongoInstallInfo in data:
for file in data.files.to_list():
binary_path.append("$TEST_SRCDIR/_main/" + file.short_path.replace("bin/" + file.basename, "bin/"))
binary_path = ctx.configuration.host_path_separator.join(binary_path)
suite = ctx.attr.config.files.to_list()[0].path
resmoke_args = [
"run",
"--dbpathPrefix=$TEST_UNDECLARED_OUTPUTS_DIR/data",
"--taskWorkDir=$TEST_UNDECLARED_OUTPUTS_DIR",
"--continueOnFailure",
"--suite",
suite,
] + ctx.attr.resmoke_args
if ctx.attr.evergreen_format:
resmoke_args.append("--installDir=dist-test/bin")
resmoke_args.append("--log=evg")
resmoke_args.append("--reportFile=$TEST_UNDECLARED_OUTPUTS_DIR/report.json")
resmoke_args.append("--cedarReportFile=cedar_report.json")
# Symbolization is not yet functional, SERVER-103538
resmoke_args.append("--skipSymbolization")
resmoke_args.append("--buildId=" + get_from_volatile_status(ctx, "build_id"))
resmoke_args.append("--distroId=" + get_from_volatile_status(ctx, "distro_id"))
resmoke_args.append("--executionNumber=" + get_from_volatile_status(ctx, "execution"))
resmoke_args.append("--projectName=" + get_from_volatile_status(ctx, "project"))
resmoke_args.append("--gitRevision=" + get_from_volatile_status(ctx, "revision"))
resmoke_args.append("--revisionOrderId=" + get_from_volatile_status(ctx, "revision_order_id"))
resmoke_args.append("--taskId=" + get_from_volatile_status(ctx, "task_id"))
resmoke_args.append("--taskName=" + get_from_volatile_status(ctx, "task_name"))
resmoke_args.append("--variantName=" + get_from_volatile_status(ctx, "build_variant"))
resmoke_args.append("--versionId=" + get_from_volatile_status(ctx, "version_id"))
resmoke_args.append("--requester=" + get_from_volatile_status(ctx, "requester"))
# This script is the action to run resmoke. It looks like this (abbreviated):
# PATH=$TEST_SRCDIR/_main/install-mongo/bin/:$PATH PYTHONPATH=$TEST_SRCDIR/poetry/packaging python3 resmoke.py run ... $@
# The $@ allows passing extra arguments to resmoke using --test_arg in the bazel invocation.
script = "ln -sf $TEST_SRCDIR/_main/bazel/resmoke/.resmoke_mongo_version.yml $TEST_SRCDIR/_main/\n" # workaround for resmoke assuming this location.
script = script + "PATH=" + binary_path + ":$PATH"
script = script + " " + "PYTHONPATH=" + python_path + " "
script = script + python.interpreter.path + " buildscripts/resmoke.py " + " ".join(resmoke_args) + " $@"
ctx.actions.write(
output = ctx.outputs.executable,
content = script,
)
resmoke_deps = [ctx.attr.resmoke[PyInfo].transitive_sources]
deps = depset(transitive = [python.files] + resmoke_deps)
runfiles = ctx.runfiles(files = deps.to_list() + ctx.files.data + ctx.files.deps + ctx.files.srcs + [ctx.version_file])
return [DefaultInfo(runfiles = runfiles)]
_resmoke_suite_test = rule(
implementation = _resmoke_suite_test_impl,
attrs = {
"config": attr.label(allow_files = True),
"data": attr.label_list(allow_files = True),
"deps": attr.label_list(allow_files = True),
"needs_mongo": attr.bool(default = False),
"needs_mongod": attr.bool(default = False),
"resmoke": attr.label(default = "//buildscripts:resmoke"),
"resmoke_args": attr.string_list(),
"srcs": attr.label_list(allow_files = True),
"evergreen_format": attr.bool(default = False),
},
toolchains = ["@bazel_tools//tools/python:toolchain_type"],
test = True,
)
def resmoke_suite_test(
name,
config,
data = [],
deps = [],
resmoke_args = [],
srcs = [],
tags = [],
timeout = "eternal",
needs_mongo = False,
needs_mongod = False,
needs_mongos = False,
**kwargs):
install_deps = []
if needs_mongo:
install_deps.append("//:install-mongo")
if needs_mongod:
install_deps.append("//:install-mongod")
if needs_mongos:
install_deps.append("//:install-mongos")
_resmoke_suite_test(
name = name,
config = config,
data = data + [
config,
"//bazel/resmoke:resmoke_mongo_version",
"//bazel/resmoke:off_feature_flags",
"//buildscripts/resmokeconfig:all_files", # This needs to be reduced, SERVER-103610
"//src/mongo/util/version:releases.yml",
] + select({
"//bazel/resmoke:in_evergreen_enabled": ["//:installed-dist-test"],
"//conditions:default": install_deps,
}),
srcs = srcs,
deps = deps,
resmoke_args = resmoke_args,
timeout = timeout,
tags = tags + ["local", "no-cache"],
evergreen_format = select({
"//bazel/resmoke:in_evergreen_enabled": True,
"//conditions:default": False,
}),
**kwargs
)

View File

@ -0,0 +1,25 @@
#! /bin/sh
# This script is used as a workspace status command
# bazel test --workspace_status_command=bazel/resmoke/volatile_status.sh
# to populate key-value pairs in bazel-out/volatile-status.txt.
# This file and the key-values can be consumed by bazel rules, but bazel
# pretends this file never changes when deciding what to rebuild.
# Evergreen expansions used primarily for Resmoke telemetry
echo build_id ${build_id}
echo distro_id ${distro_id}
echo execution ${execution}
echo project ${project}
echo revision ${revision}
echo revision_order_id ${revision_order_id}
echo task_id ${task_id}
echo task_name ${task_name}
echo build_variant ${build_variant}
echo version_id ${version_id}
echo requester ${requester}
# The current set of disabled feature flags. It would be better to remove this
# as it risks breaking the contract of volatile-status.txt. Changes to feature
# flag state should invalidate actions that consume this. SERVER-103590
echo off_feature_flags $(python bazel/resmoke/get_off_feature_flags.py)

View File

@ -0,0 +1,133 @@
load("//bazel/resmoke:resmoke.bzl", "resmoke_suite_test")
package(default_visibility = ["//visibility:public"])
filegroup(
name = "all_files",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
# This is an experimental test target for running running the jstests core
# suite as a bazel test. It runs in an experimental Evergreen task on an
# infrequent build variant. You should not worry about this target being
# perfectly up-to-date with the sutie config, nor create similar bazel targets
# for other suites. Cleanup with SERVER-103537.
resmoke_suite_test(
name = "core",
srcs = [
"//jstests/core:all_javascript_files",
"//jstests/core/administrative:all_javascript_files",
"//jstests/core/administrative/apply_ops:all_javascript_files",
"//jstests/core/administrative/current_op:all_javascript_files",
"//jstests/core/administrative/profile:all_javascript_files",
"//jstests/core/capped:all_javascript_files",
"//jstests/core/catalog:all_javascript_files",
"//jstests/core/catalog/collstats:all_javascript_files",
"//jstests/core/catalog/libs:all_javascript_files",
"//jstests/core/catalog/views:all_javascript_files",
"//jstests/core/cluster_parameters:all_javascript_files",
"//jstests/core/cluster_scalability_misc:all_javascript_files",
"//jstests/core/clustered:all_javascript_files",
"//jstests/core/ddl:all_javascript_files",
"//jstests/core/diagnostics:all_javascript_files",
"//jstests/core/global_catalog:all_javascript_files",
"//jstests/core/index:all_javascript_files",
"//jstests/core/index/covered:all_javascript_files",
"//jstests/core/index/fts:all_javascript_files",
"//jstests/core/index/geo:all_javascript_files",
"//jstests/core/index/hashed:all_javascript_files",
"//jstests/core/index/text:all_javascript_files",
"//jstests/core/index/wildcard:all_javascript_files",
"//jstests/core/js:all_javascript_files",
"//jstests/core/query:all_javascript_files",
"//jstests/core/query/all:all_javascript_files",
"//jstests/core/query/and:all_javascript_files",
"//jstests/core/query/api:all_javascript_files",
"//jstests/core/query/array:all_javascript_files",
"//jstests/core/query/batch_write:all_javascript_files",
"//jstests/core/query/bulk:all_javascript_files",
"//jstests/core/query/collation:all_javascript_files",
"//jstests/core/query/count:all_javascript_files",
"//jstests/core/query/cursor:all_javascript_files",
"//jstests/core/query/date:all_javascript_files",
"//jstests/core/query/dbref:all_javascript_files",
"//jstests/core/query/delete:all_javascript_files",
"//jstests/core/query/distinct:all_javascript_files",
"//jstests/core/query/doc_validation:all_javascript_files",
"//jstests/core/query/elemmatch:all_javascript_files",
"//jstests/core/query/exists:all_javascript_files",
"//jstests/core/query/explain:all_javascript_files",
"//jstests/core/query/expr:all_javascript_files",
"//jstests/core/query/find:all_javascript_files",
"//jstests/core/query/find_and_modify:all_javascript_files",
"//jstests/core/query/geo:all_javascript_files",
"//jstests/core/query/in:all_javascript_files",
"//jstests/core/query/inc:all_javascript_files",
"//jstests/core/query/internal_hash_eq:all_javascript_files",
"//jstests/core/query/js:all_javascript_files",
"//jstests/core/query/json_schema:all_javascript_files",
"//jstests/core/query/map_reduce:all_javascript_files",
"//jstests/core/query/mod:all_javascript_files",
"//jstests/core/query/ne:all_javascript_files",
"//jstests/core/query/nin:all_javascript_files",
"//jstests/core/query/not:all_javascript_files",
"//jstests/core/query/number:all_javascript_files",
"//jstests/core/query/objid:all_javascript_files",
"//jstests/core/query/or:all_javascript_files",
"//jstests/core/query/parsing:all_javascript_files",
"//jstests/core/query/plan_cache:all_javascript_files",
"//jstests/core/query/project:all_javascript_files",
"//jstests/core/query/pull:all_javascript_files",
"//jstests/core/query/push:all_javascript_files",
"//jstests/core/query/query_settings:all_javascript_files",
"//jstests/core/query/queryable_encryption:all_javascript_files",
"//jstests/core/query/regex:all_javascript_files",
"//jstests/core/query/release_memory:all_javascript_files",
"//jstests/core/query/rename:all_javascript_files",
"//jstests/core/query/sbe:all_javascript_files",
"//jstests/core/query/set:all_javascript_files",
"//jstests/core/query/sort:all_javascript_files",
"//jstests/core/query/top:all_javascript_files",
"//jstests/core/query/type:all_javascript_files",
"//jstests/core/query/unset:all_javascript_files",
"//jstests/core/query/update:all_javascript_files",
"//jstests/core/query/where:all_javascript_files",
"//jstests/core/replicate_record_ids:all_javascript_files",
"//jstests/core/repro:all_javascript_files",
"//jstests/core/shell:all_javascript_files",
"//jstests/core/stable_api:all_javascript_files",
"//jstests/core/testing:all_javascript_files",
"//jstests/core/timeseries:all_javascript_files",
"//jstests/core/timeseries/ddl:all_javascript_files",
"//jstests/core/timeseries/geo:all_javascript_files",
"//jstests/core/timeseries/libs:all_javascript_files",
"//jstests/core/timeseries/query:all_javascript_files",
"//jstests/core/timeseries/write:all_javascript_files",
"//jstests/core/txns:all_javascript_files",
"//jstests/core/txns/libs:all_javascript_files",
"//jstests/core/txns/timeseries:all_javascript_files",
"//jstests/core/views:all_javascript_files",
"//jstests/core/write:all_javascript_files",
"//jstests/core/write/bulk:all_javascript_files",
"//jstests/core/write/delete:all_javascript_files",
"//jstests/core/write/delete/libs:all_javascript_files",
"//jstests/core/write/empty_ts:all_javascript_files",
"//jstests/core/write/insert:all_javascript_files",
"//jstests/core_standalone:all_javascript_files",
],
config = ":suites/core.yml",
data = [
"//jstests/hooks:all_javascript_files",
"//src/third_party/schemastore.org:schemas",
],
needs_mongo = True,
needs_mongod = True,
resmoke_args = [
"--jobs=8",
"--storageEngineCacheSizeGB=1",
],
tags = [
"manual", # exclude from expansion of target pattern wildcards (..., :*, :all, etc.)
],
)

View File

@ -34,6 +34,7 @@ from buildscripts.util.read_config import read_config_file
BASE_16_TO_INT = 16
COLLECTOR_ENDPOINT = "otel-collector.prod.corp.mongodb.com:443"
BAZEL_GENERATED_OFF_FEATURE_FLAGS = "bazel/resmoke/off_feature_flags.txt"
def validate_and_update_config(parser, args, should_configure_otel=True):
@ -321,7 +322,10 @@ be invoked as either:
# These logging messages start with # becuase the output of this file must produce
# valid yaml. This comments out these print statements when the output is parsed.
print("# Fetching feature flags...")
all_ff = gen_all_feature_flag_list.get_all_feature_flags_turned_off_by_default()
if os.path.exists(BAZEL_GENERATED_OFF_FEATURE_FLAGS):
all_ff = process_feature_flag_file(BAZEL_GENERATED_OFF_FEATURE_FLAGS)
else:
all_ff = gen_all_feature_flag_list.get_all_feature_flags_turned_off_by_default()
print("# Fetched feature flags...")
else:
all_ff = []
@ -843,8 +847,8 @@ def _tags_from_list(tags_list):
def _update_symbolizer_secrets():
"""Open `expansions.yml`, get values for symbolizer secrets and update their values inside config.py ."""
if not _config.EVERGREEN_TASK_ID:
# not running on Evergreen
if not _config.EVERGREEN_TASK_ID or _config.SKIP_SYMBOLIZATION:
# not running on Evergreen or explicitly skipping symbolization
return
yml_data = utils.load_yaml_file(_config.EXPANSIONS_FILE)
_config.SYMBOLIZER_CLIENT_SECRET = yml_data.get("symbolizer_client_secret")

View File

@ -34,5 +34,9 @@ py_library(
"opentelemetry-exporter-otlp-proto-common",
group = "testing",
),
dependency(
"shrub-py",
group = "testing",
),
],
)

View File

@ -499,6 +499,13 @@ class TestRunner(Subcommand):
)
return
if not os.path.exists(config.EVERGREEN_PROJECT_CONFIG_PATH):
self._resmoke_logger.warning(
"Skipping local invocation because the Evergreen config '%s' does not exist.",
config.EVERGREEN_PROJECT_CONFIG_PATH,
)
return
evg_conf = parse_evergreen_file(config.EVERGREEN_PROJECT_CONFIG_PATH)
suite = self._get_suites()[0]

View File

@ -1478,6 +1478,24 @@ functions:
- *f_expansions_write
- *bazel_coverage_sh
"bazel test sh": &bazel_test_sh
command: subprocess.exec
display_name: "bazel test sh"
type: test
params:
binary: bash
continue_on_err: true
add_expansions_to_env: true
args:
- "src/evergreen/bazel_test.sh"
"run resmoke suite with bazel":
- *f_expansions_write
- *bazel_test_sh
- command: attach.results
params:
file_location: report.json
"generate version expansions": &generate_version_expansions
command: subprocess.exec
display_name: "generate version expansions"

View File

@ -1096,6 +1096,24 @@ tasks:
--verbose_failures
--instrumentation_filter="^//src/mongo[/:],-^//src/mongo/util:boost_assert_shim,-^//src/mongo/util:icu,-^//src/mongo/db/modules/enterprise/src/streams[/:]"
# Experimental task running the jscore suite bazel target. To be removed with SERVER-103537.
- name: bazel_test_jscore
tags: ["assigned_to_jira_team_devprod_correctness", "experimental"]
depends_on:
- name: archive_dist_test
commands:
- func: "git get project and add git tag"
- func: "do setup"
- func: "get engflow creds"
- func: "run resmoke suite with bazel"
vars:
target: //buildscripts/resmokeconfig:core
args: >-
--config=no-remote-exec
--test_output=all
--workspace_status_command="bazel/resmoke/volatile_status.sh"
--//bazel/resmoke:in_evergreen
- name: monitor_build_status
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]
commands:

View File

@ -26,3 +26,21 @@ buildvariants:
- name: monitor_build_status
distros:
- ubuntu2404-large
# Experimental variant running bazel targets for integration tests. To be removed with SERVER-103537.
- name: bazel-integration-tests
display_name: "~ Bazel Integration Tests"
tags: ["experimental"]
cron: "0 4 * * 0" # Every week starting 0400 UTC Sunday
stepback: false
run_on:
- amazon2023-arm64-latest-small
depends_on:
- name: archive_dist_test
variant: amazon-linux2023-arm64-static-compile
- name: archive_jstestshell
variant: amazon-linux2023-arm64-static-compile
expansions:
compile_variant: amazon-linux2023-arm64-static-compile
tasks:
- name: bazel_test_jscore

43
evergreen/bazel_test.sh Normal file
View File

@ -0,0 +1,43 @@
# Usage:
# bazel_test [arguments]
#
# Required environment variables:
# * ${target} - Test target
# * ${args} - Extra command line args to pass to "bazel test"
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)"
. "$DIR/prelude.sh"
cd src
set -o errexit
set -o verbose
activate_venv
# Use `eval` to force evaluation of the environment variables in the echo statement:
eval echo "Execution environment: Args: ${args} Target: ${target}"
source ./evergreen/bazel_utility_functions.sh
BAZEL_BINARY=$(bazel_get_binary_path)
# Print command being run to file that can be uploaded
echo "python buildscripts/install_bazel.py" > bazel-invocation.txt
echo "bazel test ${args} ${target}" >> bazel-invocation.txt
set +e
# use eval since some flags have quotes-in-quotes that are otherwise misinterpreted
eval $BAZEL_BINARY test ${args} ${target}
ret=$?
set -e
# For a target //path:test, the undeclared test outputs are in
# bazel-testlogs/path/test/test.outputs/outputs.zip
outputs=bazel-testlogs/$(sed "s|//||;s|:|/|" <<< ${target})/test.outputs/outputs.zip
if [ -f $outputs ]; then
unzip $outputs -d ../
fi
exit $ret

View File

@ -0,0 +1,6 @@
package(default_visibility = ["//visibility:public"])
filegroup(
name = "schemas",
srcs = glob(["src/schemas/json/*.json"]),
)