diff --git a/BUILD.bazel b/BUILD.bazel index efeacc6f1b3f4..d733df225489a 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -25,7 +25,10 @@ filegroup( name = "rakefile", srcs = [ "Rakefile", - ] + glob(["rake_tasks/*.rake", "rake_tasks/*.rb"]), + ] + glob([ + "rake_tasks/*.rake", + "rake_tasks/*.rb", + ]), visibility = ["//rb:__subpackages__"], ) diff --git a/dotnet/BUILD.bazel b/dotnet/BUILD.bazel index cd1310b0300dc..04764e8989855 100644 --- a/dotnet/BUILD.bazel +++ b/dotnet/BUILD.bazel @@ -1,5 +1,5 @@ load("@rules_pkg//pkg:zip.bzl", "pkg_zip") -load("//dotnet:defs.bzl", "nuget_push") +load("//dotnet:defs.bzl", "dotnet_format", "nuget_push", "paket_deps") load("//dotnet/private:docfx.bzl", "docfx") exports_files([ @@ -51,3 +51,17 @@ nuget_push( "//dotnet/src/webdriver:webdriver-pack", ], ) + +paket_deps( + name = "paket-update", + mode = "update", +) + +paket_deps( + name = "paket-install", + mode = "install", +) + +dotnet_format( + name = "format", +) diff --git a/dotnet/defs.bzl b/dotnet/defs.bzl index 54cb362e6ca3b..f13662f63ca60 100644 --- a/dotnet/defs.bzl +++ b/dotnet/defs.bzl @@ -1,5 +1,6 @@ load("@rules_dotnet//dotnet:defs.bzl", _csharp_binary = "csharp_binary", _csharp_library = "csharp_library", _csharp_test = "csharp_test") load("//dotnet:selenium-dotnet-version.bzl", "SUPPORTED_DEVTOOLS_VERSIONS") +load("//dotnet/private:dotnet_format.bzl", _dotnet_format = "dotnet_format") load("//dotnet/private:dotnet_nunit_test_suite.bzl", _dotnet_nunit_test_suite = "dotnet_nunit_test_suite") load("//dotnet/private:generate_devtools.bzl", _generate_devtools = "generate_devtools") load("//dotnet/private:generate_resources.bzl", _generated_resource_utilities = "generated_resource_utilities") @@ -8,6 +9,7 @@ load("//dotnet/private:nuget_pack.bzl", _nuget_pack = "nuget_pack") load("//dotnet/private:nuget_package.bzl", _nuget_package = "nuget_package") load("//dotnet/private:nuget_push.bzl", _nuget_push = "nuget_push") load("//dotnet/private:nunit_test.bzl", _nunit_test = "nunit_test") +load("//dotnet/private:paket_deps.bzl", _paket_deps = "paket_deps") def devtools_version_targets(): targets = [] @@ -18,6 +20,7 @@ def devtools_version_targets(): csharp_binary = _csharp_binary csharp_library = _csharp_library csharp_test = _csharp_test +dotnet_format = _dotnet_format dotnet_nunit_test_suite = _dotnet_nunit_test_suite generate_devtools = _generate_devtools generated_resource_utilities = _generated_resource_utilities @@ -26,3 +29,4 @@ nuget_pack = _nuget_pack nuget_package = _nuget_package nuget_push = _nuget_push nunit_test = _nunit_test +paket_deps = _paket_deps diff --git a/dotnet/private/dotnet_format.bzl b/dotnet/private/dotnet_format.bzl new file mode 100644 index 0000000000000..919c9a2d2b962 --- /dev/null +++ b/dotnet/private/dotnet_format.bzl @@ -0,0 +1,125 @@ +"""Rule for running dotnet format using the Bazel-managed dotnet toolchain.""" + +def _dotnet_format_impl(ctx): + toolchain = ctx.toolchains["@rules_dotnet//dotnet:toolchain_type"] + dotnet = toolchain.runtime.files_to_run.executable + + is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]) + + if is_windows: + script = _create_windows_script(ctx, dotnet) + else: + script = _create_unix_script(ctx, dotnet) + + runfiles = ctx.runfiles(files = [dotnet]) + runfiles = runfiles.merge(toolchain.runtime.default_runfiles) + + return [ + DefaultInfo( + executable = script, + runfiles = runfiles, + ), + ] + +def _to_runfiles_path(short_path): + """Convert a short_path to a runfiles path.""" + if short_path.startswith("../"): + return short_path[3:] + return "_main/" + short_path + +def _create_unix_script(ctx, dotnet): + """Create bash script for Unix/macOS/Linux.""" + dotnet_runfiles_path = _to_runfiles_path(dotnet.short_path) + + script_content = """#!/usr/bin/env bash +set -euo pipefail + +# Locate runfiles directory +if [[ -d "$0.runfiles/_main" ]]; then + RUNFILES_DIR="$0.runfiles" +elif [[ -n "${{RUNFILES_DIR:-}}" ]]; then + RUNFILES_DIR="$RUNFILES_DIR" +else + echo "ERROR: Could not locate runfiles directory" >&2 + exit 1 +fi + +DOTNET="$RUNFILES_DIR/{dotnet}" + +# Find the workspace root +WORKSPACE_ROOT="${{BUILD_WORKSPACE_DIRECTORY:-$RUNFILES_DIR/_main}}" +DOTNET_DIR="$WORKSPACE_ROOT/dotnet" + +cd "$DOTNET_DIR" + +echo "Running dotnet format on all projects..." +find "$DOTNET_DIR/src" "$DOTNET_DIR/test" -name "*.csproj" 2>/dev/null | while read -r proj; do + echo " Formatting $proj..." + "$DOTNET" format "$proj" || exit 1 +done || exit 1 + +echo "Done." +""".format( + dotnet = dotnet_runfiles_path, + ) + + script = ctx.actions.declare_file(ctx.label.name + ".sh") + ctx.actions.write( + output = script, + content = script_content, + is_executable = True, + ) + return script + +def _create_windows_script(ctx, dotnet): + """Create batch script for Windows.""" + dotnet_runfiles_path = _to_runfiles_path(dotnet.short_path).replace("/", "\\") + + script_content = """@echo off +setlocal + +set RUNFILES_DIR=%~dp0%~n0.runfiles +set DOTNET=%RUNFILES_DIR%\\{dotnet_path} + +if defined BUILD_WORKSPACE_DIRECTORY ( + set WORKSPACE_ROOT=%BUILD_WORKSPACE_DIRECTORY% +) else ( + set WORKSPACE_ROOT=%RUNFILES_DIR%\\_main +) +set DOTNET_DIR=%WORKSPACE_ROOT%\\dotnet + +cd /d "%DOTNET_DIR%" + +echo Running dotnet format on all projects... +for /r "%DOTNET_DIR%\\src" %%%%p in (*.csproj) do ( + echo Formatting %%%%p... + "%DOTNET%" format "%%%%p" || exit /b 1 +) +for /r "%DOTNET_DIR%\\test" %%%%p in (*.csproj) do ( + echo Formatting %%%%p... + "%DOTNET%" format "%%%%p" || exit /b 1 +) + +echo Done. +""".format( + dotnet_path = dotnet_runfiles_path, + ) + + script = ctx.actions.declare_file(ctx.label.name + ".bat") + ctx.actions.write( + output = script, + content = script_content, + is_executable = True, + ) + return script + +dotnet_format = rule( + implementation = _dotnet_format_impl, + attrs = { + "_windows_constraint": attr.label( + default = "@platforms//os:windows", + ), + }, + executable = True, + toolchains = ["@rules_dotnet//dotnet:toolchain_type"], +) diff --git a/dotnet/private/paket_deps.bzl b/dotnet/private/paket_deps.bzl new file mode 100644 index 0000000000000..7925d104a6155 --- /dev/null +++ b/dotnet/private/paket_deps.bzl @@ -0,0 +1,143 @@ +"""Rule for running paket commands using the Bazel-managed dotnet toolchain.""" + +def _paket_deps_impl(ctx): + toolchain = ctx.toolchains["@rules_dotnet//dotnet:toolchain_type"] + dotnet = toolchain.runtime.files_to_run.executable + + is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]) + + if is_windows: + script = _create_windows_script(ctx, dotnet) + else: + script = _create_unix_script(ctx, dotnet) + + runfiles = ctx.runfiles(files = [dotnet]) + runfiles = runfiles.merge(toolchain.runtime.default_runfiles) + + return [ + DefaultInfo( + executable = script, + runfiles = runfiles, + ), + ] + +def _to_runfiles_path(short_path): + """Convert a short_path to a runfiles path.""" + if short_path.startswith("../"): + return short_path[3:] + return "_main/" + short_path + +def _create_unix_script(ctx, dotnet): + """Create bash script for Unix/macOS/Linux.""" + dotnet_runfiles_path = _to_runfiles_path(dotnet.short_path) + mode = ctx.attr.mode + + script_content = """#!/usr/bin/env bash +set -euo pipefail + +# Locate runfiles directory +if [[ -d "$0.runfiles/_main" ]]; then + RUNFILES_DIR="$0.runfiles" +elif [[ -n "${{RUNFILES_DIR:-}}" ]]; then + RUNFILES_DIR="$RUNFILES_DIR" +else + echo "ERROR: Could not locate runfiles directory" >&2 + exit 1 +fi + +DOTNET="$RUNFILES_DIR/{dotnet}" + +# Find the workspace root (where dotnet/.config/dotnet-tools.json lives) +WORKSPACE_ROOT="${{BUILD_WORKSPACE_DIRECTORY:-$RUNFILES_DIR/_main}}" +DOTNET_DIR="$WORKSPACE_ROOT/dotnet" + +if [[ ! -f "$DOTNET_DIR/.config/dotnet-tools.json" ]]; then + echo "ERROR: Could not find dotnet/.config/dotnet-tools.json" >&2 + echo "Make sure you're running from the workspace root" >&2 + exit 1 +fi + +cd "$DOTNET_DIR" + +echo "Restoring dotnet tools..." +"$DOTNET" tool restore + +echo "Running paket {mode}..." +"$DOTNET" tool run paket {mode} + +echo "Done. Now run: bazel run @rules_dotnet//tools/paket2bazel:paket2bazel -- --dependencies-file $(pwd)/paket.dependencies --output-folder $(pwd)" +""".format( + dotnet = dotnet_runfiles_path, + mode = mode, + ) + + script = ctx.actions.declare_file(ctx.label.name + ".sh") + ctx.actions.write( + output = script, + content = script_content, + is_executable = True, + ) + return script + +def _create_windows_script(ctx, dotnet): + """Create batch script for Windows.""" + dotnet_runfiles_path = _to_runfiles_path(dotnet.short_path).replace("/", "\\") + mode = ctx.attr.mode + + script_content = """@echo off +setlocal + +set RUNFILES_DIR=%~dp0%~n0.runfiles +set DOTNET=%RUNFILES_DIR%\\{dotnet_path} + +if defined BUILD_WORKSPACE_DIRECTORY ( + set WORKSPACE_ROOT=%BUILD_WORKSPACE_DIRECTORY% +) else ( + set WORKSPACE_ROOT=%RUNFILES_DIR%\\_main +) +set DOTNET_DIR=%WORKSPACE_ROOT%\\dotnet + +if not exist "%DOTNET_DIR%\\.config\\dotnet-tools.json" ( + echo ERROR: Could not find dotnet\\.config\\dotnet-tools.json >&2 + exit /b 1 +) + +cd /d "%DOTNET_DIR%" + +echo Restoring dotnet tools... +"%DOTNET%" tool restore +if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% + +echo Running paket {mode}... +"%DOTNET%" tool run paket {mode} +if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% + +echo Done. Now run: bazel run @rules_dotnet//tools/paket2bazel:paket2bazel -- --dependencies-file %cd%\\paket.dependencies --output-folder %cd% +""".format( + dotnet_path = dotnet_runfiles_path, + mode = mode, + ) + + script = ctx.actions.declare_file(ctx.label.name + ".bat") + ctx.actions.write( + output = script, + content = script_content, + is_executable = True, + ) + return script + +paket_deps = rule( + implementation = _paket_deps_impl, + attrs = { + "mode": attr.string( + doc = "Paket command to run: 'update' for latest versions, 'install' to sync lockfile", + mandatory = True, + values = ["update", "install"], + ), + "_windows_constraint": attr.label( + default = "@platforms//os:windows", + ), + }, + executable = True, + toolchains = ["@rules_dotnet//dotnet:toolchain_type"], +) diff --git a/scripts/format.sh b/scripts/format.sh index 2d80782b1f1f5..23dbbef6302c7 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -14,6 +14,10 @@ section "Buildifier" echo " buildifier" >&2 bazel run //:buildifier +section "Dotnet" +echo " dotnet format" >&2 +bazel run //dotnet:format + section "Java" echo " google-java-format" >&2 find "$PWD/java" -type f -name '*.java' | xargs "$GOOGLE_JAVA_FORMAT" --replace