Skip to content

Latest commit

 

History

History
303 lines (193 loc) · 17 KB

contributing.md

File metadata and controls

303 lines (193 loc) · 17 KB

Set up your machine to contribute

These instructions will get you ready to contribute to this project. If you just want to use Aspire, see using-latest-daily.md.

Contents

Getting set up

Prepare the machine

See machine-requirements.md.

Using the dotnet CLI

After restore, dotnet commands run from this repo use the repo-local SDK because global.json includes .dotnet in the SDK search path. Use ./dotnet.sh on Unix or .\dotnet.cmd on Windows when you need to force the repo-local SDK explicitly.

Build the repo

First run ./restore.sh (macOS and Linux) or .\restore.cmd (Windows) to install the repo-local .NET SDK. Then build with ./build.sh (macOS and Linux) or .\build.cmd (Windows).

The repository uses the .NET 11 SDK pinned in global.json and .NET 10/11 runtimes. The default library target is net10.0; multitargeted libraries also target net11.0. The CLI targets net11.0. .NET 8/9 SDKs and runtimes are not needed for local builds or tests. MSBuild tasks retain a net472 target for Visual Studio, and compiler-hosted analyzers retain netstandard2.0.

Builds treat warnings as errors, except for the repository-wide WarningsNotAsErrors policy. The build entry points evaluate eng/WarningPolicy.proj, which imports Directory.Build.props, with the build's configuration and MSBuild property arguments. They forward the resulting exemptions through Arcade's -warnNotAsError option so they also apply to its standalone NuGet restore. Additional exemptions supplied with that option are merged with the evaluated policy; warning codes do not need to be duplicated in the scripts. Cleanup (-clean) skips this evaluation and does not require installing the SDK.

NuGet auditing uses https://data.nuget.org/v3/index.json for vulnerability metadata, independently of the package download feeds. Vulnerability findings remain visible as warnings by default. Pass /p:TreatNuGetAuditWarningsAsErrors=true to make them errors instead. Arcade disables auditing for official builds; this behavior is unchanged. These exemptions do not remediate vulnerable dependencies.

Verify your setup

Run TestShop

This will confirm that you're all set up.

In your shell or in VS Code:

dotnet restore playground/TestShop/TestShop.AppHost/TestShop.AppHost.csproj
dotnet run --project playground/TestShop/TestShop.AppHost/TestShop.AppHost.csproj

dotnet run delegates to aspire run for local orchestration. To publish deployment artifacts, use aspire publish instead of passing --operation publish to dotnet run.

Or, if you are using Visual Studio:

  1. Open Aspire.slnx
  2. Set the Startup Project to be the AppHost project (it's under \playground\TestShop). Make sure the launch profile is set to "http".
  3. F5 to debug, or Ctrl+F5 to launch without debugging.

View Dashboard

When you start the sample app in Visual Studio, it will automatically open your browser to show the dashboard.

Otherwise if you are using the command line, when you have the Aspire app running, open the dashboard URL in your browser. The URL is shown in the app's console output like this: Now listening on: http://localhost:15888. You can change the default URL in the launchSettings.json file in the AppHost project.

Testing

Running tests

To run tests, use the build script:

./build.sh --test  # Linux/macOS
.\build.cmd --test # Windows

Quarantined and outerloop tests

Flaky tests may be marked as quarantined to prevent them from blocking CI while being investigated and fixed. See quarantined-tests.md for more information on working with quarantined tests.

Long-running or resource-intensive tests may be marked as outerloop. See outerloop-tests.md for more information.

When running tests locally or in automated environments, use the test filters to exclude known flaky and outerloop tests:

dotnet test --no-launch-profile -- \
  --filter-not-trait "quarantined=true" \
  --filter-not-trait "outerloop=true"

Testing pull request changes

To test changes from a specific pull request locally, see dogfooding-pull-requests.md for instructions on installing Aspire CLI and NuGet packages built by that PR's CI run.

To validate how the CLI resolves Aspire.* packages for staging and stable release-branch builds (including making an installed PR build behave like a staging build), see cli-staging-validation.md.

NuGet configuration in CLI unit tests

Use NuGetTestHelper.CreateClient() or CreateService() for tests that compose real NuGet configuration, and NuGetTestHelper.LoadSettings() for native settings assertions. These helpers preserve directory-level configuration inheritance while replacing the runner's user-wide settings with a controlled baseline and excluding machine-wide settings by default. Supply TestMachineWideSettings explicitly when testing machine-wide policy.

TemporaryWorkspace.CreateForCli() isolates Aspire settings, not NuGet settings. Do not change process-wide environment variables to isolate NuGet configuration in parallel tests.

Coding Agents

Aspire uses GitHub Copilot automatic code review on pull requests. We expect Copilot review comments to be reviewed and addressed before merging, either by making the requested change or by explaining why a suggested change is not needed.

The Aspire repository also includes custom Copilot skills that team members and automation may run on PRs, even when the PR author is not using an AI coding agent. Contributors can get a head start by running the key skills before requesting review:

Note

AI-based code review and end-to-end testing can help find issues earlier, but they are not a replacement for human review and manual testing. Contributors are still responsible for understanding their changes and verifying the scenarios they affect.

Reviews a PR for high-confidence problems only, such as bugs, security issues, correctness errors, performance regressions, missing boundary error handling, concurrency or resource issues, flaky test patterns, and repository convention violations. It avoids style nits and duplicate review comments.

Installs the Aspire CLI and packages from a PR's dogfood build, verifies the installed CLI matches the PR head commit, analyzes changed areas, proposes targeted happy-path and negative test scenarios, runs the selected scenarios locally or in the repo container runner, captures evidence, and can produce a PR testing report.

Guides Aspire CLI end-to-end test authoring and debugging with Hex1b terminal automation. It covers test structure, local localhive archive workflows, Docker-based execution, install modes, prompt detection, and asciinema recordings for failures.

Guides GitHub Actions test-failure diagnosis. It covers downloading failed job logs and artifacts, extracting failed tests from runs, investigating failures without filing issues, and creating or updating failing-test issues with the repo tooling.

Other repo skills can help with specialized work, but these are the main skills the Aspire team uses to evaluate PR quality, dogfoodability, CLI end-to-end coverage, and CI test failures.

Development environments

Using VS Code

Make sure you build the repo from command line at least once. Then use ./start-code.sh (macOS and Linux) or .\start-code.cmd to start VS Code.

Using Visual Studio

Make sure you build the repo from command line at least once using .\build.cmd (Windows). Then use .\startvs.cmd to start Visual Studio with the correct environment setup.

Area-specific guidance

Localization

Shared metadata in Directory.Build.targets automatically configures resource/designer pairs in each project's Resources and Properties directories. Add a neutral resource as Name.resx with its matching Name.Designer.cs; both files must exist before the shared generator metadata applies, and no per-file project entries are needed. Dotted neutral names such as Errors.Validation.resx are supported. Resource classes use ResXFileCodeGenerator (internal) by default. The Dashboard sets ResxCodeGenerator to PublicResXFileCodeGenerator to keep its resource classes public. Culture-specific files such as Name.fr.resx should not have checked-in designers and are not configured for designer generation. Unrelated designers such as Settings.Designer.cs and linked resources outside these project-local directories are unchanged. This is still Visual Studio custom-tool generation, not build-time source generation: keep the checked-in designer file synchronized with the neutral resource file.

If you are contributing to Aspire.Dashboard, please ensure that all strings are localized. If necessary, create a new resx file under src/Aspire.Dashboard/Resources. To reference a string, ensure the IStringLocalizer for the resx file is injected. An example is below:

@inject IStringLocalizer<Resources.ResxFile> Loc
...
<p>@Loc[Resources.ResxFile.YourStringHere]</p>

Note that injection doesn't happen until a component's OnInitialized, so if you are referencing a string from codebehind, you must wait to do that until OnInitialized.

The *.Designer.cs files are checked in with the matching *.resx files. If you add, remove, or rename resources, update the matching designer file too. If the project has an xlf directory, run dotnet build /t:UpdateXlf <path-to-project.csproj> to update localization files instead of editing *.xlf files manually.

Integrations

Please check the Aspire integrations contribution guidelines if you intend to make contributions to a new or existing Aspire integration.

Native build

The default build includes native builds for Aspire.Cli which produces Native AOT binaries for some platforms. These projects are in eng/clipack/Aspire.Cli.*.

By default it builds the CLI native project for the current Runtime Identifier. Specific RIDs can be specified by setting $(TargetRids) to a colon separated list like /p:TargetRids=osx-x64:osx-arm64.

Native build can be disabled with /p:SkipNativeBuild=true. To build only the native bits, use /p:SkipManagedBuild=true.

Building the VS Code extension

The Aspire VS Code extension lives under extension/. See extension/CONTRIBUTING.md for the full extension contributor guide, including the extension-only inner loop (no .NET build required), project structure, running tests, and localization rules.

To build the extension through the repo build, make sure Node.js, yarn, and vsce are on your PATH, then run:

./build.sh --build-extension  # macOS/Linux
.\build.cmd /p:BuildExtension=true # Windows

This runs the extension/Extension.proj build, installs extension dependencies with the checked-in yarn.lock, compiles the extension, and creates the VSIX artifacts under artifacts/packages/Debug/vscode.

For extension inner-loop development, you can work directly in the extension folder:

cd extension
yarn install --frozen-lockfile --non-interactive
yarn compile

Use yarn watch while editing TypeScript. When adding or changing user-facing extension text, keep the strings localized in both extension/package.nls.json and extension/src/loc/strings.ts. For VSIX signing and release packaging details, see extension-signing.md.

Trying your changes locally

Running the Aspire CLI from source

For a fast in-repo development loop, use run-aspire.sh (macOS and Linux) or run-aspire.cmd (Windows). The wrapper runs the CLI from the current worktree without installing it, preserves your current directory, and forwards any Aspire command:

cd playground/rust
../../run-aspire.sh restore
../../run-aspire.sh run

On Windows, use ..\..\run-aspire.cmd instead. Use localhive when you need to validate the complete locally built product, including packages and the bundle payload.

Generating local NuGet packages

If you only need package outputs, it can be useful to generate the NuGet packages in a local folder and use it as a package source from a separate Aspire-based project or solution. If you want to validate a complete locally-built Aspire product, including the CLI, templates, package hive, and bundle payload, use localhive instead.

To do so simply execute: ./build.sh --pack (macOS and Linux) or .\build.cmd --pack (Windows)

This will generate all the packages in the folder ./artifacts/packages/Debug/Shipping. At this point from your solution folder run:

dotnet nuget add source my_aspire_folder/artifacts/packages/Debug/Shipping

Or edit the NuGet.config file and add this line to the <packageSources> list:

<add key="aspire-dev" value="my_aspire_folder/artifacts/packages/Debug/Shipping" />

Creating a local Aspire build with localhive

Use localhive when you want a fully usable Aspire product from your local source tree, not just a folder of NuGet packages. The script builds and packs the Aspire packages, creates an Aspire hive, builds the bundle payload, and installs a locally-built Aspire CLI. The CLI then discovers the hive as a channel, so commands like aspire new, aspire add, and aspire init use the packages produced by your custom build.

Prefer using an explicit output directory so your custom build stays isolated and does not overwrite the default Aspire install under $HOME/.aspire:

./localhive.sh -c Release -n my-feature -o ./artifacts/localhive/my-feature
export PATH="$PWD/artifacts/localhive/my-feature/bin:$PATH"
aspire --version

On Windows:

.\localhive.ps1 -c Release -n my-feature -o .\artifacts\localhive\my-feature
$env:PATH = "$(Resolve-Path .\artifacts\localhive\my-feature\bin);$env:PATH"
aspire --version

To create a standalone portable build that can be copied to another machine, add a target RID and the archive flag:

./localhive.sh -c Release -n my-feature -o ./artifacts/localhive/linux-x64 -r linux-x64 --archive

On Windows:

.\localhive.ps1 -c Release -n my-feature -o .\artifacts\localhive\win-x64 -r win-x64 -Archive

The archive contains the CLI, local package hive, and bundle payload needed for that build. After extracting it on the target machine, run the aspire binary from the extracted bin directory.

Tips and known issues

Make sure you have started Docker before trying to run an Aspire app.

For information on who can help in PRs and issues, see the area owners page.

See the tips and known issues page.

Package validation

When creating a new integration, package validation will automatically try to download a previous version of the package to ensure you didn't break compat. As a result you might get the following build error:

error NU1101: Unable to find package [NEW PACKAGE NAME]. No packages exist with this id in source(s): dotnet-eng, dotnet-public, dotnet9, dotnet10, dotnet9-transport. PackageSourceMapping is enabled, the following source(s) were not considered: dotnet-libraries.

To prevent this the new package needs this line to be added to the .csproj:

<EnablePackageValidation>false</EnablePackageValidation>