Skip to content

dotnet deploy optimize skill - #11

Closed
jeffschwMSFT wants to merge 10 commits into
dotnet:mainfrom
jeffschwMSFT:skill/dotnet-deploy-optimize
Closed

dotnet deploy optimize skill#11
jeffschwMSFT wants to merge 10 commits into
dotnet:mainfrom
jeffschwMSFT:skill/dotnet-deploy-optimize

Conversation

@jeffschwMSFT

Copy link
Copy Markdown
Member

Proposing a skill for offering recommendation on how to optimize a .NET Core application during publish

Comprehensive deployment optimization skill for .NET 8+ apps covering:
- Publish modes (framework-dependent, self-contained, single-file, R2R, Native AOT)
- Publish setting compatibility matrix
- Trimming and tree-shaking
- Docker image optimization
- CI/CD pipeline tuning
- Configuration and secrets management
- Health checks and readiness probes
jeffschwMSFT and others added 4 commits February 12, 2026 13:43
Critical fixes:
- Add missing ReadyToRun + SelfContained=false conflict row
- Add Worker Service-specific health check guidance (Kestrel, publisher, TCP)
- Broaden secrets check to all appsettings*.json files

Moderate fixes:
- Add dotnet publish CLI command example alongside XML properties
- Short-circuit Step 3 (trimming) when AOT is chosen
- Tighten Worker Service detection to require BackgroundService/IHostedService
- Add AOT vs JIT tiered compilation trade-off for long-running workloads
- Add skip guard on Step 7 for apps with no config files
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 20, 2026 18:37
Users ask about fast startup and small binaries rather than
technical terms like Native AOT and trimming.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new .NET deployment optimization skill intended to help users choose appropriate dotnet publish settings (trimming/AOT/single-file), plus an eval suite to validate recommendations across common app types.

Changes:

  • Introduces dotnet-deploy-optimize skill documentation covering publish modes, trimming, Native AOT, Docker, CI/CD, config, and health checks.
  • Adds dotnet-deploy-optimize evaluation scenarios for a Web API, conflicting publish properties, and a Worker Service.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.

File Description
src/dotnet/skills/dotnet-deploy-optimize/SKILL.md New skill content describing a workflow for deployment/publish optimization and operational readiness.
src/dotnet/tests/dotnet-deploy-optimize/eval.yaml New eval scenarios to validate the skill’s recommendations across project types and settings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +225 to +234
1. Option A — Add a minimal Kestrel endpoint for health checks:

```csharp
builder.Services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy());

builder.WebHost.UseKestrel(o => o.ListenAnyIP(8080));
var app = builder.Build();
app.MapHealthChecks("/healthz");
```

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Worker Service health-check snippet uses builder.WebHost.UseKestrel(...), builder.Build(), and app.MapHealthChecks(...) without showing where builder comes from. As written, it won’t compile in a typical Worker Service template (Host.CreateDefaultBuilder / HostApplicationBuilder) and may confuse users. Suggest providing a complete, self-contained example that matches the Worker template (or explicitly state this option switches to a WebApplicationBuilder-based minimal host alongside the worker).

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +63
<PublishAot>true</PublishAot>
<PublishSingleFile>true</PublishSingleFile>
<ReadyToRun>true</ReadyToRun>
<SelfContained>false</SelfContained>
</PropertyGroup>

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The eval fixture uses <ReadyToRun>true</ReadyToRun>, but the publish property name is PublishReadyToRun. Using the wrong property here makes the scenario less realistic and can cause the agent to learn/emit an invalid setting. Recommend switching the fixture (and rubric wording) to PublishReadyToRun.

Copilot uses AI. Check for mistakes.
app.Run();
assertions:
- type: "output_contains"
value: "conflict"

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This scenario’s assertion only checks for the literal word "conflict", which doesn’t strongly validate the expected behavior (and may fail if the recommendation uses synonyms like "incompatible"). Consider asserting for the specific properties involved (e.g., PublishAot, PublishSingleFile, PublishReadyToRun, SelfContained) or using an output_matches regex that requires mentioning at least two of them.

Suggested change
value: "conflict"
value: "PublishAot"
- type: "output_contains"
value: "PublishSingleFile"
- type: "output_contains"
value: "ReadyToRun"
- type: "output_contains"
value: "SelfContained"

Copilot uses AI. Check for mistakes.
Comment on lines +101 to +106
var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
});
var host = builder.Build();

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Worker Service fixture, Host.CreateDefaultBuilder(args) returns an IHostBuilder where ConfigureServices typically takes (HostBuilderContext, IServiceCollection) rather than a single services parameter. As written, the snippet won’t compile; consider adjusting the fixture to a valid Worker template so the scenario reflects real-world code.

Suggested change
var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
});
var host = builder.Build();
using Microsoft.Extensions.Hosting;
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddHostedService<Worker>();
})
.Build();

Copilot uses AI. Check for mistakes.

1. Read the project file(s) and identify the target framework, output type, and any existing publish settings.
2. Check for a `Properties/launchSettings.json`, `appsettings.json`, and `appsettings.*.json` files.
3. Note any existing `PublishTrimmed`, `PublishAot`, `PublishSingleFile`, `ReadyToRun`, or `SelfContained` properties.

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The skill refers to the publish setting as ReadyToRun, but in .NET/MSBuild the publish property is PublishReadyToRun (see other skills in this repo). Using ReadyToRun here will mislead readers and the later compatibility matrix/rubric. Recommend renaming to PublishReadyToRun throughout (including the eval fixtures).

Suggested change
3. Note any existing `PublishTrimmed`, `PublishAot`, `PublishSingleFile`, `ReadyToRun`, or `SelfContained` properties.
3. Note any existing `PublishTrimmed`, `PublishAot`, `PublishSingleFile`, `PublishReadyToRun`, or `SelfContained` properties.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +87
| Setting A | Setting B | Outcome | Explanation |
|-----------|-----------|---------|-------------|
| `PublishAot` | `PublishSingleFile` | **Conflict** | AOT produces a single native binary by default; `PublishSingleFile` is for IL-based apps and is ignored with AOT |
| `PublishAot` | `ReadyToRun` | **Conflict** | ReadyToRun pre-compiles IL to native via crossgen; AOT replaces the IL pipeline entirely, making R2R meaningless |
| `PublishAot` | `SelfContained=false` | **Conflict** | AOT output is always self-contained; setting `SelfContained` to false is contradictory and will cause a build error |

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the compatibility matrix, the outcome is marked Conflict but the explanation says the setting is "ignored"/"meaningless". That reads like a redundant/no-op combination rather than a hard conflict (build error). Consider changing the outcome wording (e.g., "Redundant/ignored") so the guidance is unambiguous.

Copilot uses AI. Check for mistakes.
Comment on lines +101 to +105
- Heavy use of `System.Reflection` and using string representations of types, strongly typed reflection is not problematic
- Dynamic assembly loading
- `System.Text.Json` source generators not configured
- COM interop
- Check trim-compatibility of dependencies, including from nuget

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trimming bullet is a run-on sentence and hard to parse ("Heavy use of ... , strongly typed reflection..."). Also, "nuget" should be capitalized as "NuGet" here (and again in the AOT section). Recommend rewriting this bullet into clearer sub-bullets and fixing capitalization.

Suggested change
- Heavy use of `System.Reflection` and using string representations of types, strongly typed reflection is not problematic
- Dynamic assembly loading
- `System.Text.Json` source generators not configured
- COM interop
- Check trim-compatibility of dependencies, including from nuget
- Reflection usage:
- Heavy use of `System.Reflection` APIs that rely on string-based type or member names (for example, `Type.GetType("Namespace.TypeName")`)
- Strongly typed reflection (such as `typeof`, `nameof`, or expression-based access) is generally trim-safe
- Dynamic assembly loading
- `System.Text.Json` source generators not configured
- COM interop
- Check trim-compatibility of dependencies, including from NuGet

Copilot uses AI. Check for mistakes.
jeffschwMSFT and others added 3 commits February 20, 2026 12:57
The model already scores 5/5 on conflict detection without guidance.
The compatibility table added ~300 tokens without improving results,
and the skill was flagged as approaching the 'comprehensive' range
where gains diminish.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add prominent warning against defaulting to AOT for long-running
  services; explain JIT tiered compilation and dynamic PGO benefits
- Add workload lifetime decision point before recommending AOT
- Reorder worker health check options from lightest to heaviest
- Add trade-off callout for adding Kestrel to worker services
- Present file-based and TCP probes as lighter alternatives

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AOT, R2R, and tiered JIT are orthogonal trade-offs (startup, binary
size, dependencies, steady-state throughput). Present a comparison
table so the user can choose based on what they value, rather than
prescribing based on long-running vs short-lived.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jeffschwMSFT

Copy link
Copy Markdown
Member Author

well, this was my first attempt and I do not think it has the right fitness. but parts may be interesting

Skill Scenario Baseline With Skill Δ Verdict
dotnet-deploy-optimize Basic Web API publish optimization 4.0/5 3.0/5 -1.0 ⚠️
dotnet-deploy-optimize Detect conflicting publish settings 5.0/5 1.0/5 -4.0
dotnet-deploy-optimize Worker service deployment readiness 2.0/5 3.0/5 +1.0

Note: "Detect conflicting publish settings" is marked ❌ because the with-skill agent timed out at 180s with zero output delivered to the user. It spent all its time in diagnostic investigation and build output analysis, never producing any findings or recommendations. The baseline completed successfully with a 5.0/5 score, making this a significant regression in both task completion (✓→✗) and quality.

@jeffschwMSFT
jeffschwMSFT marked this pull request as draft February 21, 2026 19:03
@jeffschwMSFT
jeffschwMSFT marked this pull request as draft February 21, 2026 19:03
@jeffschwMSFT

Copy link
Copy Markdown
Member Author

the highest value of this proposed skill was the health check, which another proposed skill covers

YuliiaKovalova added a commit to YuliiaKovalova/skills that referenced this pull request May 7, 2026
…date+cleanup step

Restore content lost when orchestrator was rewritten as pure dispatcher, plus add
preventative guidance addressing the three regressions found in run 25504147640
(resolution dropped from 39%->17% vs run 25497220848).

orchestrator (code-testing-generator.agent.md):
- Step 1: reference unit-test-generation.prompt.md and pre-pipeline git stash
- Step 4: implementer dispatch prompt now embeds test-strength rubric
  (concrete-value assertions, N>=3 collection inputs, full-equality, no
  toBeTruthy-only) and file-location rules
- Step 8: restore Coverage Gap Iteration (re-research/plan/implement narrowed
  scope when rubric items remain uncovered)
- Step 9 NEW: Validate-and-cleanup dispatch to code-testing-builder which
  has terminal/edit access. Removes .testagent/, runs git diff --name-only,
  reverts SUSPICIOUS files (env/cfg/toml/source-outside-test). Addresses
  6/12 manifest_fail cases caused by .testagent/ leaking into the patch.
- Rules: add dotnet#10 (cleanup mandatory) and dotnet#11 (test strength belongs in
  implementer prompt, not tester post-hoc check)

implementer (code-testing-implementer.agent.md):
- Step 4a NEW: Test strength requirements with concrete bad/good examples,
  reserved-name keys for property iteratees, mutation-resistance check
- Step 4b NEW: File-location and side-effect rules with naming decision tree
- Rules: add dotnet#6 (test strength non-negotiable) and dotnet#7 (stay inside test dirs)

planner (code-testing-planner.agent.md):
- Step 4: Add allowed/forbidden file targets, naming decision tree, and
  scenario depth requirement (N>=3 elements with concrete expected values)

Diagnosis from run 25504147640:
- 10/41 patches contained .testagent/research.md or plan.md (no cleanup)
- mutation_fail jumped from 18 to 24 (single-element collection inputs,
  type-only assertions allowed weaker tests through)
- app-2ad2720a modified tests/test.env DB port (no rule against config edits)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
moesac0970 pushed a commit to moesac0970/skills that referenced this pull request Jul 4, 2026
…otnet - Startup-style config, NHibernate/MassTransit/Serilog notes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants