https://github.blog/changelog/2025-01-21-custom-repository-instructions-are-now-available-for-copilot-on-github-com-public-preview/
Aspire provides tools, templates, and packages for building observable, production-ready distributed applications. At its core is an app model that defines services, resources, and connections in a code-first approach.
- Aspire.Hosting: Application host orchestration and resource management
- Aspire.Dashboard: Web-based dashboard for monitoring and debugging
- Service Discovery: Infrastructure for service-to-service communication
- Integrations: 40+ packages for databases (SQL Server, PostgreSQL, Redis, MongoDB), message queues (RabbitMQ, Kafka), cloud services (Azure), and more
- CLI Tools: Command-line interface for project creation and management
- Project Templates: Starter templates for new Aspire applications
- .NET 10.0
- C# 13 preview features
- xUnit SDK v3 with Microsoft.Testing.Platform for testing
- Microsoft.DotNet.Arcade.Sdk for build infrastructure
- Native AOT compilation for CLI tools
- Multi-platform support (Windows, Linux, macOS, containers)
- Make only high confidence suggestions when reviewing code changes.
- Always use the latest version C#, currently C# 13 features.
- Never change global.json unless explicitly asked to.
- Never change package.json or package-lock.json files unless explicitly asked to.
- Never change NuGet.config files unless explicitly asked to.
- Don't update files under
*/api/*.cs(e.g. src/Aspire.Hosting/api/Aspire.Hosting.cs) as they are generated.
- Apply code-formatting style defined in
.editorconfig. - Prefer file-scoped namespace declarations and single-line using directives.
- Insert a newline before the opening curly brace of any code block (e.g., after
if,for,while,foreach,using,try, etc.). - Ensure that the final return statement of a method is on its own line.
- Use pattern matching and switch expressions wherever possible.
- Use
nameofinstead of string literals when referring to member names. - Place private class declarations at the bottom of the file.
- Declare variables non-nullable, and check for
nullat entry points. - Always use
is nulloris not nullinstead of== nullor!= null. - Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.
Always run restore first to set up the local SDK. Run ./restore.sh (Linux/macOS) or ./restore.cmd (Windows) first to install the local SDK. After restore, you can use standard dotnet commands, which will automatically use the local SDK when available due to the paths configuration in global.json.
- Restore First: Always run
./restore.sh(Linux/macOS) or./restore.cmd(Windows) to set up the local .NET SDK (~30 seconds)
- Full Build:
./build.sh(Linux/macOS) or./build.cmd(Windows) - defaults to restore + build (~3-5 minutes) - Build Only:
./build.sh --build(assumes restore already done) - Skip Native Build: Add
/p:SkipNativeBuild=trueto avoid slow native AOT compilation (~1-2 minutes saved) - Clean Build:
./build.sh --rebuild - Package Generation:
./build.sh --packto create NuGet packages
- If temporarily introducing warnings during refactoring, add
/p:TreatWarningsAsErrors=falseto prevent build failure - Important: All warnings should be addressed before committing any final changes
- Template engine warnings about "Missing generatorVersions" are expected and not errors
- If build fails with SDK errors, run
./restore.shagain to ensure correct .NET 10 RC is installed - Build artifacts go to
./artifacts/directory
- VS Code: Run
./build.shfirst, then use./start-code.shto launch with correct environment - Visual Studio: Run
./build.cmdfirst, then use./startvs.cmdto launch with local SDK environment
- We use xUnit SDK v3 with Microsoft.Testing.Platform (https://learn.microsoft.com/dotnet/core/testing/microsoft-testing-platform-intro)
- Do not emit "Act", "Arrange" or "Assert" comments.
- We do not use any mocking framework at the moment.
- Copy existing style in nearby files for test method names and capitalization.
- Do not leave newly-added tests commented out. All added tests should be building and passing.
- Do not use Directory.SetCurrentDirectory in tests as it can cause side effects when tests execute concurrently.
(1) Build from the root with ./build.sh (~3-5 minutes).
(2) If that produces errors, fix those errors and build again. Repeat until the build is successful.
(3) To run tests for a specific project: dotnet test tests/ProjectName.Tests/ProjectName.Tests.csproj --no-build -- --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
Note that tests for a project can be executed without first building from the root.
(4) To run specific tests, include the filter after --:
dotnet test tests/Aspire.Hosting.Testing.Tests/Aspire.Hosting.Testing.Tests.csproj -- --filter-method "*.TestingBuilderHasAllPropertiesFromRealBuilder" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"Important: Avoid passing --no-build unless you have just built in the same session and there have been no code changes since. In automation or while iterating on code, omit --no-build so changes are compiled and picked up by the test run.
When running tests in automated environments (including Copilot agent), always exclude quarantined and outerloop tests to avoid false negatives and long-running tests:
# Correct - excludes quarantined and outerloop tests (use this in automation)
dotnet test tests/Project.Tests/Project.Tests.csproj -- --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
# For specific test filters, combine with quarantine and outerloop exclusion
dotnet test tests/Project.Tests/Project.Tests.csproj -- --filter-method "TestName" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"Never run all tests without the quarantine and outerloop filters in automated environments, as this will include flaky tests that are known to fail intermittently and long-running tests that slow down CI.
Valid test filter switches include: --filter-class, --filter-not-class, --filter-method, --filter-not-method, --filter-namespace, --filter-not-namespace, --filter-not-trait, --filter-trait
The switches --filter-class and --filter-method expect fully qualified names, unless a filter is used as a prefix like --filter-class "*.SomeClassName" or --filter-method "*.SomeMethodName".
These switches can be repeated to run tests on multiple classes or methods at once, e.g., --filter-method "*.SomeMethodName1" --filter-method "*.SomeMethodName2".
- Single Test Project: Typical runtime ~10-60 seconds per test project
- Full Test Suite: Can take 30+ minutes, use targeted testing instead
/src: Main source code for all Aspire packagesAspire.Hosting/: Core hosting and orchestration infrastructureAspire.Dashboard/: Web dashboard UI (Blazor application)Components/: 40+ integration packages for databases, messaging, cloud servicesAspire.Cli/: Command-line interface tools
/tests: Comprehensive test suites mirroring src structure/playground: Sample applications including TestShop for verification/docs: Documentation including contributing guides and area ownership/eng: Build scripts, tools, and engineering infrastructure/.github: CI/CD workflows, issue templates, and GitHub automation/extension: VS Code extension source code
global.json: Pins .NET SDK version - never modify without explicit request.editorconfig: Code formatting rules, null annotations, diagnostic configurationsDirectory.Build.props: Shared MSBuild properties across all projectsDirectory.Packages.props: Centralized package version managementAspire.slnx: Main solution file (XML-based solution format)
tests.yml: Main test workflow running across Windows/Linux/macOStests-quarantine.yml: Runs quarantined tests separately every 6 hourstests-outerloop.yml: Runs outerloop tests separately every 6 hoursci.yml: Main CI workflow triggered on PRs and pushes to main/release branches- Build validation: Includes package generation, API compatibility checks, template validation
Dependencies and Hidden Requirements
- Local .NET SDK: Automatically uses local SDK when available after running restore due to paths configuration in global.json
- Package References: Centrally managed via Directory.Packages.props
- API Surface: Public APIs tracked in
src/*/api/*.csfiles (auto-generated, don't edit)
- Build Verification:
./build.shshould complete without errors - Package Generation:
./build.sh --packverifies all packages can be created - Specific Tests: Target individual test projects related to your changes
- Tests that are flaky and don't fail deterministically are marked with the
QuarantinedTestattribute. - Such tests are not run as part of the regular tests workflow (
tests.yml).- Instead they are run in the
Quarantineworkflow (tests-quarantine.yml).
- Instead they are run in the
- A github issue url is used with the attribute
Example: [QuarantinedTest("..issue url..")]
- To quarantine or unquarantine tests, use the tool in
tools/QuarantineTools/QuarantineTools.csproj.
- Tests that are long-running, resource-intensive, or require special infrastructure are marked with the
OuterloopTestattribute. - Such tests are not run as part of the regular tests workflow (
tests.yml).- Instead they are run in the
Outerloopworkflow (tests-outerloop.yml).
- Instead they are run in the
- An optional reason can be provided with the attribute
Example: [OuterloopTest("Long running integration test")]
- We use the Verify library (Verify.XunitV3) for snapshot testing in several test projects.
- Snapshot files are stored in
Snapshotsdirectories within test projects. - When tests that use snapshot testing are updated and generate new output, the snapshots need to be accepted.
- Use
dotnet verify accept -yto accept all pending snapshot changes after running tests. - The verify tool is available globally as part of the copilot setup.
The *.Designer.cs files are in the repo, but are intended to match same named *.resx files. If you add/remove/change resources in a resx, make the matching changes in the *.Designer.cs file that matches that resx.
- Markdown files should not have multiple consecutive blank lines.
- Code blocks should be formatted with triple backticks (```) and include the language identifier for syntax highlighting.
- JSON code blocks should be indented properly.
- Files matching the pattern
*/localize/templatestrings.*.jsonare localization files. Do not translate their content. It is done by a dedicated workflow.
These instructions are comprehensive and tested. Only search for additional information if:
- The instructions appear outdated or incorrect
- You encounter specific errors not covered here
- You need details about new features not yet documented
For most development tasks, following these instructions should be sufficient to build, test, and validate changes successfully.
- When possible, you should create Typescript files instead of Javascript files.
- You must not use dynamic imports unless absolutely necessary. Instead, use static imports.
- When displaying text to the user, ensure that the strings are localized. New localized strings must be put both in the extension
package.nls.jsonand alsosrc/loc/strings.ts.