dotnet-artifacts-output
npx skills add https://github.com/novotnyllc/dotnet-artisan --skill dotnet-artifacts-output
Agent 安装分布
Skill 文档
dotnet-artifacts-output
Reference guide for the .NET SDK artifacts output layout, which centralizes build outputs (bin/, obj/, publish/, package/) into a single artifacts/ directory at the repo root. Available since .NET 8 as an opt-in feature. Recommended for new projects; evaluate tradeoffs before migrating existing projects.
Prerequisites: Run [skill:dotnet-version-detection] first to confirm .NET 8+ SDK — artifacts output layout is not available in earlier SDK versions.
Scope
- UseArtifactsOutput opt-in and ArtifactsPath configuration
- Centralized build output layout (artifacts/bin/, artifacts/obj/, artifacts/publish/)
- Impact on CI artifact upload paths and Docker builds
- Migration tradeoffs for existing projects
Out of scope
- Source tree organization (.sln, .csproj, src/, tests/) — see [skill:dotnet-project-structure]
Cross-references: [skill:dotnet-project-structure] for solution layout, [skill:dotnet-containers] for Dockerfile path adjustments, [skill:dotnet-gha-build-test] for CI artifact upload paths, [skill:dotnet-scaffold-project] for generating new projects with artifacts output enabled.
Why Use Artifacts Output
Traditional .NET build output scatters bin/ and obj/ directories throughout the source tree, one per project. The artifacts output layout consolidates all build outputs under a single artifacts/ directory next to Directory.Build.props.
Benefits:
- Simpler
.gitignore— oneartifacts/entry replaces per-projectbin/andobj/entries - Easier clean builds — delete one directory instead of hunting for scattered
bin//obj/folders - Predictable output paths — tooling can anticipate where to find build outputs without traversing the source tree
- Cleaner source tree — no build artifacts mixed into project directories
Tradeoffs:
- Breaking path assumptions — existing CI pipelines, Dockerfiles, and tooling that reference
bin/Debug/net10.0/paths must be updated - IDE/tool compatibility — some older tools may not resolve the new output paths correctly
- Migration effort — existing projects require updating all hardcoded output path references
Enabling Artifacts Output
Add UseArtifactsOutput to your Directory.Build.props at the repo root:
<Project>
<PropertyGroup>
<UseArtifactsOutput>true</UseArtifactsOutput>
</PropertyGroup>
</Project>
Alternatively, generate a new Directory.Build.props with artifacts output pre-configured:
dotnet new buildprops --use-artifacts
This creates:
<Project>
<PropertyGroup>
<ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>
</PropertyGroup>
</Project>
Setting ArtifactsPath directly is equivalent to UseArtifactsOutput=true and additionally lets you customize the root directory location.
Output Path Structure
All build outputs are organized under artifacts/ with three levels: output type, project name, and pivot (configuration/TFM/RID).
artifacts/
bin/
MyApp/
debug/ # Single-targeted project
debug_net10.0/ # Multi-targeted project
release_linux-x64/ # RID-specific build
MyApp.Core/
debug/
obj/
MyApp/
debug/
publish/
MyApp/
release/ # dotnet publish output
release_linux-x64/ # RID-specific publish
package/
release/ # NuGet .nupkg files (no project subfolder)
Output Type Directories
| Directory | Contents | Traditional equivalent |
|---|---|---|
artifacts/bin/ |
Compiled assemblies and dependencies | <project>/bin/ |
artifacts/obj/ |
Intermediate build files, generated code | <project>/obj/ |
artifacts/publish/ |
Published application output | <project>/bin/<config>/<tfm>/publish/ |
artifacts/package/ |
NuGet packages (.nupkg, .snupkg) |
<project>/bin/<config>/ |
Pivot Naming
The pivot subfolder combines configuration, TFM, and RID joined by underscores. Components that are not present are omitted:
| Scenario | Pivot | Full path example |
|---|---|---|
| Single-targeted, debug | debug |
artifacts/bin/MyApp/debug/ |
| Multi-targeted, debug | debug_net10.0 |
artifacts/bin/MyApp/debug_net10.0/ |
| Release, RID-specific | release_linux-x64 |
artifacts/bin/MyApp/release_linux-x64/ |
| Package output | release |
artifacts/package/release/ |
Note: artifacts/package/ omits the project name subfolder. The pivot includes only the configuration.
Customizing the Artifacts Path
Custom Root Directory
Set ArtifactsPath to change the root location:
<PropertyGroup>
<ArtifactsPath>$(MSBuildThisFileDirectory).output</ArtifactsPath>
</PropertyGroup>
This places all build outputs under .output/ instead of artifacts/.
Custom Pivot
Customize the pivot subfolder naming with ArtifactsPivots:
<PropertyGroup>
<ArtifactsPivots>$(ArtifactsPivots)_MyCustomPivot</ArtifactsPivots>
</PropertyGroup>
Impact on .gitignore
With artifacts output enabled, simplify .gitignore:
# Artifacts output layout (replaces per-project bin/ and obj/ entries)
artifacts/
This single entry replaces the traditional pattern:
# Traditional layout (no longer needed with artifacts output)
[Bb]in/
[Oo]bj/
If using a custom ArtifactsPath, update the .gitignore entry to match.
Impact on Dockerfiles
Multi-stage Dockerfiles that copy build output must reference the new path structure. See [skill:dotnet-containers] for full Dockerfile patterns.
Traditional paths:
COPY /app/src/MyApp/bin/Release/net10.0/publish/ .
Artifacts output paths:
COPY /app/artifacts/publish/MyApp/release/ .
Key differences in Dockerfile paths:
- Output is under
artifacts/publish/notbin/Release/<tfm>/publish/ - Project name becomes a subdirectory under the output type
- Configuration pivot is lowercase (
releasenotRelease) - TFM is omitted from single-targeted project pivots
Impact on CI Pipelines
CI workflows that upload build artifacts or reference output paths must be updated. See [skill:dotnet-gha-build-test] for full CI workflow patterns.
GitHub Actions — upload build output:
- name: Publish
run: dotnet publish src/MyApp/MyApp.csproj -c Release
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: app
path: artifacts/publish/MyApp/release/
GitHub Actions — upload NuGet packages:
- name: Pack
run: dotnet pack -c Release
- name: Upload packages
uses: actions/upload-artifact@v4
with:
name: packages
path: artifacts/package/release/*.nupkg
Azure DevOps — publish artifacts:
- script: dotnet publish src/MyApp/MyApp.csproj -c Release
displayName: 'Publish'
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'artifacts/publish/MyApp/release/'
artifact: 'app'
Migration Checklist
When enabling artifacts output on an existing project:
- Add
UseArtifactsOutputtoDirectory.Build.props - Update
.gitignore— replace[Bb]in/and[Oo]bj/withartifacts/ - Update Dockerfiles — change all
COPY --from=buildpaths to useartifacts/structure - Update CI pipelines — fix artifact upload paths, test result paths, and publish paths
- Update local scripts — fix any shell scripts that reference
bin/orobj/paths - Clean old output — delete existing
bin/andobj/directories from all projects - Verify builds — run
dotnet buildanddotnet publishto confirm output appears underartifacts/ - Verify tests — run
dotnet testto confirm test execution with new paths
Agent Gotchas
- Do not hardcode TFM in artifacts output paths for single-targeted projects. The pivot for single-targeted projects is just the configuration (e.g.,
debug), notdebug_net10.0. Multi-targeted projects include the TFM in the pivot. - Do not use capitalized configuration names in artifacts paths. The artifacts layout uses lowercase pivots (
debug,release), not the traditional capitalized names (Debug,Release). - Do not assume
artifacts/package/has a project name subfolder. Unlikebin/,obj/, andpublish/, thepackage/output type omits the project name level. Packages appear directly underartifacts/package/<config>/. - Do not enable artifacts output without updating Dockerfiles and CI pipelines first. Path changes will break
COPY --from=builddirectives and artifact upload steps that reference traditionalbin/paths. - Do not present artifacts output as the default .NET layout. It is opt-in since .NET 8 and remains opt-in. Recommend it for new projects; for existing projects, evaluate the migration effort against the benefits.