How the ASP.NET Core eng Directory Powers the Development Workflow
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 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 performs several critical initialization steps:
- Sets sensible defaults, such as building managed projects when no specific group is specified (lines 88‑96).
- Applies CI-specific tweaks, including binary logging and
ulimitadjustments when the--ciflag is present (lines 71‑78). - Bootstraps the Microsoft Arcade toolset by importing
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.shandInstallGoogleChrome.ps1spin up required external tools on CI agents.update-selenium-and-playwright-versions.ps1synchronizes browser automation versions withVersions.props.CodeCheck.ps1validates thatDependencies.propsand theDependabotDiscoveryproject 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 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:
# 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 and resolve via the Arcade toolset, ensuring consistent behavior across Windows, macOS, and Linux.
Summary
- The
engdirectory centralizes all build, test, and packaging logic for the ASP.NET Core repository, acting as the single integration point for Microsoft Arcade. eng/build.shserves as the universal entry point, parsing arguments and bootstrapping the toolset viaeng/common/tools.sh.eng/Versions.propsandeng/Dependencies.propseliminate 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 theDependabotDiscoverytooling 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 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, 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →