# How the ASP.NET Core eng Directory Powers the Development Workflow

> Discover how the ASP.NET Core eng directory streamlines development. Learn about its role in building, testing, packaging, and publishing across platforms and CI.

- Repository: [.NET Platform/aspnetcore](https://github.com/dotnet/aspnetcore)
- Tags: internals
- Published: 2026-08-01

---

**The `eng` directory serves as the centralized build infrastructure backbone for ASP.NET Core, housing shell scripts, MSBuild targets, and shared properties that standardize building, testing, packaging, and publishing across all platforms and CI systems.**

The `dotnet/aspnetcore` repository relies on this dedicated folder to maintain consistency across its massive, multi-platform codebase. By encapsulating version management, dependency resolution, and test orchestration in one location, the **eng directory** ensures that local developer workflows and automated Azure DevOps pipelines execute identical build logic. Any modification to the build process made within `eng` automatically propagates to all consuming projects throughout the repository.

## Build Orchestration and Entry Points

The [`eng/build.sh`](https://github.com/dotnet/aspnetcore/blob/main/eng/build.sh) script functions as the primary entry point for developers and CI agents. Located at the root of the `eng` folder, this Bash script parses CLI arguments—such as `--configuration`, `--arch`, `--os-name`, `--build-managed`, and `--build-nodejs` (lines 58‑78)—and constructs a unified `msbuild_args` array that feeds into the MSBuild engine (lines 115‑156).

When invoked, [`build.sh`](https://github.com/dotnet/aspnetcore/blob/main/build.sh) performs several critical initialization steps:

1. **Sets sensible defaults**, such as building managed projects when no specific group is specified (lines 88‑96).
2. **Applies CI-specific tweaks**, including binary logging and `ulimit` adjustments when the `--ci` flag is present (lines 71‑78).
3. **Bootstraps the Microsoft Arcade toolset** by importing [`eng/common/tools.sh`](https://github.com/dotnet/aspnetcore/blob/main/eng/common/tools.sh) (line 81), which resolves the correct .NET SDK, restores necessary tools, and prepares the MSBuild environment.

The `build.ps1` and `build.cmd` scripts are thin wrappers around this same logic, guaranteeing identical behavior across Windows PowerShell, Windows Command Prompt, and Unix-based shells.

## Centralized Version and Dependency Management

Two property files within the `eng` directory act as the single source of truth for all versioning concerns.

**`eng/Versions.props`** defines core ASP.NET Core version components (`AspNetCoreMajorVersion`, `AspNetCoreMinorVersion`), pre-release labeling (`PreReleaseVersionLabel`, `PreReleaseVersionIteration`), and property-based version pins for third-party packages. For example, line 57 specifies `<GoogleProtobufVersion>3.27.0</GoogleProtobufVersion>`. Every project file imports this props file, ensuring version consistency eliminates drift across the codebase.

**`eng/Dependencies.props`** catalogs every external NuGet package as a `<LatestPackageReference>` item. A subsequent ItemGroup resolves each entry to concrete versions using the properties defined in `Versions.props` (lines 65‑78). This centralization enables source-only builds to pull packages from the `dotnet-public` feed and supplies runtime-specific RID packages for Crossgen2 and native runtimes (lines 107‑129).

## Modular MSBuild Targets

The `eng/targets/` directory contains modular `.targets` files that extend MSBuild functionality for specific scenarios:

- **Wix packaging** for installer generation.
- **Helix test execution** for distributed testing.
- **Functional-test asset management** for end-to-end validation.
- **Multi-language support** for C#, F#, C++, and NodeJS builds.

These files are imported by individual project files, allowing the build system to compose complex pipelines from discrete, maintainable components rather than embedding logic directly in `.csproj` files.

## CI/CD Integration and Helix Test Orchestration

The `eng/helix/helix.proj` file configures Azure’s distributed test runner, Helix. This project defines targets that prepare the test environment (installing Node.js, JDK, and Chrome), upload test binaries and logs to Helix queues, and report results back to Azure DevOps. Functional-test projects reference these targets, enabling a single command—`dotnet build /bl`—to trigger end-to-end test execution on Microsoft-hosted infrastructure.

Supporting scripts in `eng/scripts/` automate environment setup and validation:

- [`install-nginx.sh`](https://github.com/dotnet/aspnetcore/blob/main/install-nginx.sh) and `InstallGoogleChrome.ps1` spin up required external tools on CI agents.
- `update-selenium-and-playwright-versions.ps1` synchronizes browser automation versions with `Versions.props`.
- `CodeCheck.ps1` validates that `Dependencies.props` and the `DependabotDiscovery` project remain in sync.

## Automation-Friendly Tooling

The `eng/tools/DependabotDiscovery/` directory contains a "fake" project (`DependabotDiscovery.csproj`) designed specifically for dependency management automation. By mirroring external packages as `<PackageReference>` entries, this project allows Dependabot to discover and bump versions automatically. The [`README.md`](https://github.com/dotnet/aspnetcore/blob/main/README.md) in this directory explains how the tool integrates with the central dependency catalog, ensuring automated updates flow back into `eng/Versions.props` correctly.

Additional property files like `eng/TrimmableProjects.props` and `eng/Signing.props` provide fine-grained controls for assembly trimming and code-signing artifacts during the publishing phase.

## Practical Usage Examples

The following commands demonstrate how the `eng` directory facilitates common development tasks:

```bash

# Build default (managed) projects in Debug on current OS/arch

./eng/build.sh

# Build only NodeJS assets, skipping managed compilation

./eng/build.sh --no-build-managed --build-nodejs

# Perform a CI-ready Release build with binary logging

./eng/build.sh --ci --configuration Release

# Build a specific project without its dependencies

./eng/build.sh --no-build-deps --projects src/Mvc/Mvc.csproj

# Run Helix tests for a functional test project

dotnet test src/Testing/FunctionalTests/FunctionalTests.csproj /p:RunHelixTests=true

```

All options parse through [`eng/build.sh`](https://github.com/dotnet/aspnetcore/blob/main/eng/build.sh) and resolve via the Arcade toolset, ensuring consistent behavior across Windows, macOS, and Linux.

## Summary

- The `eng` directory centralizes all build, test, and packaging logic for the ASP.NET Core repository, acting as the single integration point for Microsoft Arcade.
- **[`eng/build.sh`](https://github.com/dotnet/aspnetcore/blob/main/eng/build.sh)** serves as the universal entry point, parsing arguments and bootstrapping the toolset via [`eng/common/tools.sh`](https://github.com/dotnet/aspnetcore/blob/main/eng/common/tools.sh).
- **`eng/Versions.props`** and **`eng/Dependencies.props`** eliminate version drift by providing a unified catalog of package versions and runtime dependencies.
- Modular MSBuild targets in **`eng/targets/`** handle specialized tasks like Wix packaging and Helix test execution without polluting individual project files.
- Automation scripts in **`eng/scripts/`** and the **`DependabotDiscovery`** tooling ensure CI environments remain reproducible and dependencies stay current.

## Frequently Asked Questions

### What is the primary purpose of the eng directory in ASP.NET Core?

The `eng` directory houses the repository's build infrastructure, including shell scripts, MSBuild properties, and automation tools. It standardizes how developers and CI systems compile code, run tests, and produce packages by centralizing shared logic that would otherwise be duplicated across hundreds of project files.

### How does eng/build.sh differ from build.cmd or build.ps1?

[`eng/build.sh`](https://github.com/dotnet/aspnetcore/blob/main/eng/build.sh) is the canonical Bash implementation that contains the full argument parsing logic and MSBuild invocation sequence. `build.cmd` and `build.ps1` are thin wrappers that delegate to this script (or its PowerShell equivalent), ensuring that Windows and Unix developers invoke identical build semantics regardless of shell environment.

### What role does Microsoft Arcade play in the eng directory?

Microsoft Arcade is the shared build infrastructure used across .NET repositories. The `eng` directory imports Arcade via [`eng/common/tools.sh`](https://github.com/dotnet/aspnetcore/blob/main/eng/common/tools.sh), which handles SDK resolution, tool restoration, and environment preparation. This integration allows ASP.NET Core to inherit centralized build improvements and maintain consistency with other dotnet repositories.

### How does the eng directory handle automated dependency updates?

The `eng/tools/DependabotDiscovery` project creates a synthetic CSPROJ file containing `<PackageReference>` entries for all external dependencies. This allows Dependabot to detect outdated packages and propose version bumps. The `eng/scripts/CodeCheck.ps1` script validates that these references remain synchronized with `eng/Dependencies.props` during CI runs, preventing configuration drift.