Skip to content

[dotnet] [build] Simplify how we pack nuget package#17270

Merged
nvborisenko merged 7 commits intoSeleniumHQ:trunkfrom
nvborisenko:dotnet-build-pack
Mar 29, 2026
Merged

[dotnet] [build] Simplify how we pack nuget package#17270
nvborisenko merged 7 commits intoSeleniumHQ:trunkfrom
nvborisenko:dotnet-build-pack

Conversation

@nvborisenko
Copy link
Copy Markdown
Member

Eliminate unnecessary zipping.

💥 What does this PR do?

This pull request refactors and simplifies the NuGet packaging logic in dotnet/private/nuget_pack.bzl by removing the intermediate zip step, streamlining the file layout process, and cleaning up unused attributes. The changes improve maintainability and efficiency by directly copying files into the package structure and generating the .csproj template in a more reusable way.

NuGet packaging process simplification:

  • Removed the use of an intermediate zip file during the NuGet package creation process; files are now copied directly into the working directory in their final layout, reducing complexity and potential errors. [1] [2]
  • Refactored the file layout logic by replacing the paths dictionary with a layout dictionary for clearer intent and easier management of files within the package.
  • Consolidated and simplified the .csproj file generation by introducing a reusable _CSPROJ_TEMPLATE string, and removed the redundant property_group_vars attribute from the rule and its usages. [1] [2] [3] [4]

Code and rule cleanup:

  • Removed the _zip tool and related logic from the rule definition, as zipping is no longer necessary. [1] [2]
  • Cleaned up and clarified the _guess_dotnet_version function by removing the unused label parameter and improving comments for maintainability.

🔄 Types of changes

  • Cleanup (formatting, renaming)

@selenium-ci selenium-ci added C-dotnet .NET Bindings B-build Includes scripting, bazel and CI integrations labels Mar 29, 2026
@qodo-code-review
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Simplify NuGet package creation by eliminating intermediate zip

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Removed intermediate zip file step during NuGet packaging
• Refactored file layout logic using direct file copying
• Consolidated .csproj template generation with reusable string
• Removed unused property_group_vars attribute and _zip tool
• Simplified _guess_dotnet_version function by removing label parameter

Grey Divider

File Changes

1. dotnet/private/nuget_pack.bzl ✨ Enhancement +83/-94

Eliminate zip intermediate and streamline packaging logic

• Introduced _CSPROJ_TEMPLATE constant for reusable project file generation
• Removed intermediate zip file creation; files now copied directly to working directory
• Refactored _guess_dotnet_version to remove unused label parameter
• Replaced paths dictionary with layout dictionary for clearer intent
• Removed property_group_vars rule attribute and _zip tool dependency
• Restructured command building using list of command parts joined with &&

dotnet/private/nuget_pack.bzl


2. dotnet/src/webdriver/BUILD.bazel Cleanup +0/-4

Remove unused property_group_vars attribute

• Removed property_group_vars attribute from nuget_pack rule invocation

dotnet/src/webdriver/BUILD.bazel


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review bot commented Mar 29, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Stale workdir contaminates package🐞 Bug ⛯ Reliability
Description
nuget_pack_impl copies inputs and runs dotnet pack inside a fixed execroot folder
("<target>-working-dir") without cleaning it, so stale files from prior builds (or concurrent
builds) can be included in the produced .nupkg/.snupkg. Because the working directory isn’t declared
as an output, Bazel won’t manage or clean it, making the package contents potentially
non-deterministic across runs.
Code

dotnet/private/nuget_pack.bzl[R78-97]

+    working_dir = ctx.label.name + "-working-dir"
+
+    # Copy files directly into the working directory layout (no intermediate zip)
+    copy_cmds = []
+    for (file, rel_path) in layout.items():
+        dest = working_dir + "/" + rel_path
+        copy_cmds.append("mkdir -p $(dirname {dest}) && cp {src} {dest}".format(
+            dest = dest,
+            src = file.path,
+        ))
+
+    cmd_parts = [
+        "mkdir -p " + working_dir,
+    ] + copy_cmds + [
+        "cp {src} {dir}/project.nuspec".format(src = nuspec.path, dir = working_dir),
+        "cp {src} {dir}/project.csproj".format(src = csproj_file.path, dir = working_dir),
+        "cd " + working_dir,
+        "echo '<configuration><packageSources><clear /><add key=\"local\" value=\"%CWD%/{packages}\" /></packageSources></configuration>' >nuget.config".format(
+            packages = packages.path,
+        ),
Evidence
The action uses a fixed path (ctx.label.name + "-working-dir") and creates it with mkdir -p, then
copies files into it and runs dotnet restore/pack there; nothing removes the directory or ensures
it starts empty. The run_shell action only declares the final .nupkg/.snupkg as outputs, so the
working directory is not tracked/cleaned by Bazel between builds.

dotnet/private/nuget_pack.bzl[78-99]
dotnet/private/nuget_pack.bzl[123-133]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The packaging action writes into a fixed, undeclared working directory (`<target>-working-dir`) and does not clean it. This can cause stale files to remain and be accidentally included in subsequent packages, and can also lead to cross-action clobbering.

### Issue Context
The `CreateNupkg` action currently declares only the final `.nupkg`/`.snupkg` as outputs, but it performs substantial work in a persistent execroot directory.

### Fix Focus Areas
- dotnet/private/nuget_pack.bzl[78-133]

### Suggested fix directions (pick one)
1) **Clean before use**: prepend `rm -rf "${working_dir}" && mkdir -p "${working_dir}"`.
2) **Use a declared output directory**: `working_dir = ctx.actions.declare_directory(...)` and add it to `outputs` for the `CreateNupkg` action, using `working_dir.path` everywhere.
3) **Use a temp dir**: `WORKDIR=$(mktemp -d)`; ensure copy/pack happens there and it’s removed at end.

Also consider quoting paths in shell commands when implementing the cleanup to avoid path parsing issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unquoted paths in cp📘 Rule violation ⛨ Security
Description
The new run_shell commands build cp invocations by string-concatenating file paths without
quoting/argument separation, which can break on whitespace/shell metacharacters and is unsafe path
handling for tooling scripts. This violates the hardening requirement for build/CI/scripts path
handling.
Code

dotnet/private/nuget_pack.bzl[R84-87]

+        copy_cmds.append("mkdir -p $(dirname {dest}) && cp {src} {dest}".format(
+            dest = dest,
+            src = file.path,
+        ))
Evidence
PR Compliance ID 14 requires safe path handling in scripts/tooling; the updated packaging flow
constructs shell commands like cp {src} {dest} and cp <joined paths> without quoting or passing
paths as separate arguments, creating whitespace-splitting/edge-case risks.

dotnet/private/nuget_pack.bzl[60-62]
dotnet/private/nuget_pack.bzl[84-87]
dotnet/private/nuget_pack.bzl[92-93]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`nuget_pack_impl()` constructs shell commands by concatenating unquoted paths into `cp` commands (and `cp` with a space-joined list). This can break on whitespace/special characters and does not meet safe path handling expectations for build/tooling.

## Issue Context
This PR removed the intermediate zip and now does direct file layout via `run_shell`, increasing reliance on correct shell quoting/argument handling.

## Fix Focus Areas
- dotnet/private/nuget_pack.bzl[60-62]
- dotnet/private/nuget_pack.bzl[84-87]
- dotnet/private/nuget_pack.bzl[92-93]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. files assumes one artifact 📘 Rule violation ⛯ Reliability
Description
The updated layout logic indexes file.files.to_list()[0] without validating that the label
produces exactly one file, which can fail with a non-actionable error or select an unintended file.
This violates the requirement to validate external/config-derived inputs early with clear
exceptions.
Code

dotnet/private/nuget_pack.bzl[R49-50]

    for (file, name) in ctx.attr.files.items():
-        paths[file.files.to_list()[0]] = name
-
-    # Zip everything up so we have the right file structure
-    zip_file = ctx.actions.declare_file("%s-intermediate.zip" % ctx.label.name)
-    args = ctx.actions.args()
-    args.add_all(["Cc", zip_file])
-    for (file, path) in paths.items():
-        args.add("%s=%s" % (path, file.path))
-    args.add("project.nuspec=%s" % (nuspec.path))
-
-    ctx.actions.run(
-        executable = ctx.executable._zip,
-        arguments = [args],
-        inputs = paths.keys() + [nuspec],
-        outputs = [zip_file],
-    )
-
-    # Now lay everything out on disk and execute the dotnet pack rule
+        layout[file.files.to_list()[0]] = name
Evidence
PR Compliance ID 11 requires early validation with actionable errors; the new code assumes each
files entry has at least one output file and blindly takes index 0, rather than checking length
and failing with a clear message.

dotnet/private/nuget_pack.bzl[49-50]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The code assumes each label in `ctx.attr.files` yields at least one file and selects the first (`to_list()[0]`), which can crash or behave unexpectedly when the label produces zero or multiple files.

## Issue Context
`files` is an external input to the rule; failures should be explicit and actionable (e.g., "must produce exactly one file").

## Fix Focus Areas
- dotnet/private/nuget_pack.bzl[49-50]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@nvborisenko nvborisenko merged commit bdfda79 into SeleniumHQ:trunk Mar 29, 2026
18 of 19 checks passed
@nvborisenko nvborisenko deleted the dotnet-build-pack branch March 29, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-build Includes scripting, bazel and CI integrations C-dotnet .NET Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants