NuGet Paketi Yayınlamak: dotnet pack, Paket Metadata'sı, Package Validation ve nuget.org Trusted Publishing
NuGet paketini metadata, README, lisans ve symbol paketiyle oluştur, EnablePackageValidation ile önceki sürümü baseline alıp kazara breaking change'i pack sırasında yakala, nuget.org'a ise uzun ömürlü API key yerine OIDC ile bir saatlik key veren trusted publishing ile yayınla. Bookstore.Contracts'ta isteğe bağlı parametrenin binary kırılmasını CP0002 ile, framework kaldırmayı PKV006 ile, aynı sürümün ikinci push'unu yerel sunucuda 409 Conflict ile gösteriyoruz.
Sürüm notu: Bu yazıdaki örnekler .NET 10 (SDK 10.0.402), MinVer 8.0.0, BaGetter (Docker'da yerel NuGet sunucusu) ve actionlint 1.7.12 ile denenmiştir. Trusted publishing workflow'u actionlint ile doğrulandı; GitHub'da ve nuget.org'da koşulmadı.
Önce Tahmin Et
Sitedeki serilerin ortak örnek uygulaması Bookstore'un (bir online kitapçı) Bookstore.Contracts paketi 2.0.0'da. Emre, kitaplara yayınevi bilgisini eklemek istiyor ve mevcut kullanıcıları kırmamak için yeni parametreyi isteğe bağlı yapıyor:
// 2.0.0
public sealed record BookDto(string Isbn, string Title, string Author, Money ListPrice);
// sonraki sürüm: isteğe bağlı bir parametre
public sealed record BookDto(string Isbn, string Title, string Author, Money ListPrice, string? Publisher = null);
Eski kod new BookDto(isbn, title, author, price) diye yazılmış; yeniden derlendiğinde hata almıyor. Bu değişiklik 2.1.0 olarak yayınlanabilir mi? Paketi 2.0.0'ı baseline alarak package validation ile oluşturalım:
$ dotnet pack src/Bookstore.Contracts -c Release -o artifacts \
-p:PackageValidationBaselineVersion=2.0.0 \
-p:RestoreAdditionalProjectSources=$PWD/artifacts/feed
Successfully created package 'artifacts/Bookstore.Contracts.2.0.1-alpha.0.2.nupkg'.
error CP0002: Member 'Bookstore.Contracts.BookDto.BookDto(string, string, string, Bookstore.Contracts.Money)' exists on [Baseline] lib/net10.0/Bookstore.Contracts.dll but not on lib/net10.0/Bookstore.Contracts.dll
error CP0002: Member 'void Bookstore.Contracts.BookDto.Deconstruct(out string, out string, out string, out Bookstore.Contracts.Money)' exists on [Baseline] lib/net10.0/Bookstore.Contracts.dll but not on lib/net10.0/Bookstore.Contracts.dll
error : API breaking changes found. If those are intentional, the APICompat suppression file can be updated by rebuilding with '/p:ApiCompatGenerateSuppressionFile=true'
Yayınlanamaz. İsteğe bağlı parametre kaynak seviyesinde uyumlu, ama binary seviyesinde değil: derleyici varsayılan değeri çağıran tarafa yazıyor ve 2.0.0'a göre derlenmiş bir assembly, artık var olmayan dört parametreli constructor'ı arıyor. Yeniden derlenmeden 2.1.0'la çalışan bir uygulama MissingMethodException alır. Record'un ürettiği Deconstruct da aynı sebeple değişti. Bu yazıda paketi doğru metadata ile oluşturmayı, bu tür kırılmaları yayından önce yakalamayı ve nuget.org'a API key saklamadan yayınlamayı ele alıyoruz.
Paket Tasarımı: Metadata, README, Lisans ve Symbol Paketi
C# Temelleri serisinin "C# Kodu Düzenlemek: Namespace, global using, Solution ve NuGet" yazısında NuGet paketini tüketen taraftan görmüştük. Yayınlayan taraf için dotnet pack'in ürettiği paketin sayfası, arama sonucu ve güven sinyalleri csproj'daki property'lerden geliyor:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<!-- Sürüm contracts/v1.2.0 gibi tag'lerden gelir -->
<MinVerTagPrefix>contracts/v</MinVerTagPrefix>
</PropertyGroup>
<PropertyGroup>
<PackageId>Bookstore.Contracts</PackageId>
<Description>Shared DTOs of the Bookstore API (books, prices) for .NET clients.</Description>
<Authors>Bookstore Team</Authors>
<PackageTags>bookstore;dto;contracts</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageProjectUrl>https://github.com/example/bookstore</PackageProjectUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<EnablePackageValidation>true</EnablePackageValidation>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="/" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MinVer" Version="8.0.0" PrivateAssets="all" />
</ItemGroup>
</Project>
Her satırın bir sebebi var. PackageId paketin değişmez kimliği; nuget.org'da bir kez alındıktan sonra başka biri kullanamıyor. Description ve PackageTags aramada görünüyor. PackageLicenseExpression bir SPDX (Software Package Data Exchange; lisansları standart kısa adlarla tanımlayan format) ifadesi; nuget.org lisansı bu ifadeden tanıyor. PackageReadmeFile paket sayfasında gösterilen README'yi pakete koyuyor; dosyayı None item'ıyla paketin köküne eklemek gerekiyor. Paket ikonu için PackageIcon aynı biçimde çalışıyor; Bookstore'da şimdilik ikon yok. PublishRepositoryUrl, Source Link'in bulduğu repository adresini ve commit'i nuspec'e yazıyor. GenerateDocumentationFile XML dokümantasyonunu pakete ekliyor; IDE'de kullanıcı tooltip'lerde açıklamaları görüyor. IncludeSymbols ve SymbolPackageFormat ise pdb'leri ayrı bir .snupkg'ye koyuyor; nuget.org bunu symbol server'ında tutuyor ve bir önceki yazılarda gördüğümüz Source Link bilgisiyle birlikte debugger kaynağa inebiliyor.
$ dotnet pack src/Bookstore.Contracts -c Release -o artifacts
Successfully created package 'artifacts/Bookstore.Contracts.2.0.1-alpha.0.1.nupkg'.
Successfully created package 'artifacts/Bookstore.Contracts.2.0.1-alpha.0.1.snupkg'.
$ unzip -l artifacts/Bookstore.Contracts.2.0.1-alpha.0.1.nupkg
Length Date Time Name
--------- ---------- ----- ----
482 11-14-2026 07:12 _rels/.rels
839 11-14-2026 07:12 Bookstore.Contracts.nuspec
390 11-14-2026 04:12 README.md
8704 11-14-2026 04:12 lib/net10.0/Bookstore.Contracts.dll
2497 11-14-2026 04:12 lib/net10.0/Bookstore.Contracts.xml
582 11-14-2026 07:12 [Content_Types].xml
701 11-14-2026 07:12 package/services/metadata/core-properties/nuget.psmdcp
Üretilen nuspec, metadata'nın gerçekten pakete girdiğini gösteriyor:
<metadata>
<id>Bookstore.Contracts</id>
<version>2.0.1-alpha.0.1</version>
<authors>Bookstore Team</authors>
<license type="expression">MIT</license>
<licenseUrl>https://licenses.nuget.org/MIT</licenseUrl>
<readme>README.md</readme>
<projectUrl>https://github.com/example/bookstore</projectUrl>
<description>Shared DTOs of the Bookstore API (books, prices) for .NET clients.</description>
<tags>bookstore dto contracts</tags>
<repository type="git" url="https://github.com/example/bookstore.git" branch="refs/heads/main" commit="a257ef9e6e37abf55f4353277420a3657dde20da" />
<dependencies>
<group targetFramework="net10.0" />
</dependencies>
</metadata>
repository satırındaki commit, paketin hangi koddan derlendiğini nuget.org'da herkese gösteriyor. Sürüm 2.0.1-alpha.0.1, çünkü son tag'den sonra bir commit var; MinVer'in bu davranışını üçüncü yazıda görmüştük.
Target Framework Seçimi
Paketin hangi framework'leri hedeflediği de kullanıcıya verilen bir söz. .NET 8 ve .NET 9'un desteği 10 Kasım 2026'da bitti; destekte olan sürümler .NET 10 (LTS; Long Term Support, uzun süreli destek) ve .NET 11. Bookstore.Contracts bu yüzden yalnız net10.0 hedefliyor. Hâlâ .NET 8'de kalmış bir kurumsal istemciyi desteklemen gerekseydi <TargetFrameworks>net8.0;net10.0</TargetFrameworks> ile iki hedefe birden derleyebilirdin; .NET Framework'ü de kapsaman gerekiyorsa netstandard2.0 eklemek gerekir, ama record ve init gibi özellikler için ek tanımlar ister.
Burada sessiz bir tuzak var. Desteği biten framework için SDK'nın verdiği NETSDK1138 uyarısını denedik: SDK 10.0.402 bu uyarıyı yalnız executable projelerde verdi ve listesinde net7.0 vardı, net8.0 yoktu. Bir library net8.0 hedeflediğinde hiçbir uyarı çıkmadı; aynı denemede .NET 11 SDK'sı da sessiz kaldı. Desteği biten framework'ü takip etmek senin işin.
Framework eklemek minor bir değişiklik, kaldırmak ise breaking change: o framework'teki kullanıcılar yeni sürüme geçemez. Package validation bunu da yakalıyor. Ayrı bir denemede net8.0;net10.0 hedefleyen 2.1.0'ı baseline alıp yalnız net10.0 hedefleyen 2.2.0'ı paketlediğimizde:
error PKV006: Target framework net8.0 is no longer supported in the latest version.
Package Validation: Baseline ile Kırılmayı Build'de Yakalamak
EnablePackageValidation açıkken dotnet pack paketi oluşturduktan sonra birkaç kontrol yapıyor. Baseline olmadan da paketin kendi içindeki tutarlılığa bakıyor: ör. farklı framework'ler için derlenen assembly'lerin public API'leri birbiriyle uyumlu mu. Asıl değerli kontrol ise PackageValidationBaselineVersion verildiğinde başlıyor: SDK bu sürümü feed'den indiriyor ve yeni paketin her framework'ünü baseline'daki karşılığıyla API seviyesinde karşılaştırıyor. Arkasında Microsoft.DotNet.ApiCompat'in kuralları çalışıyor; aynı kontrolleri build dışında çalıştırmak için ayrı bir Microsoft.DotNet.ApiCompat.Tool aracı da var.
Baseline sürümü csproj'a yazmadık, komut satırından veriyoruz: her release'te değişen bir değer ve csproj'da durursa, baseline'ı feed'de bulamayan her build restore aşamasında düşer. Yerelde nuget.org yerine bir klasör feed'i kullandık; 2.0.0'ı oraya koymak için:
$ dotnet pack src/Bookstore.Contracts -c Release -o artifacts/feed -p:MinVerVersionOverride=2.0.0
Successfully created package 'artifacts/feed/Bookstore.Contracts.2.0.0.nupkg'.
Successfully created package 'artifacts/feed/Bookstore.Contracts.2.0.0.snupkg'.
Tahmin bölümündeki komut bu klasörü RestoreAdditionalProjectSources ile ek kaynak olarak veriyor. CI'da baseline doğrudan nuget.org'dan ya da şirketin feed'inden geliyor. Hatanın çözümü, yeni bilgiyi constructor'a değil bir init property'sine koymak:
namespace Bookstore.Contracts;
/// <summary>A book as returned by the Bookstore API.</summary>
/// <param name="Isbn">ISBN-13 of the book.</param>
/// <param name="Title">Title of the book.</param>
/// <param name="Author">Author name.</param>
/// <param name="ListPrice">Current list price with currency.</param>
public sealed record BookDto(string Isbn, string Title, string Author, Money ListPrice)
{
/// <summary>Publisher name, if known.</summary>
public string? Publisher { get; init; }
}
Bu hâliyle validation geçiyor ve değişiklik gerçekten bir minor: eski constructor ve Deconstruct yerinde, yeni property isteğe bağlı. Kırılma bilinçliyse (bir major hazırlıyorsan) -p:ApiCompatGenerateSuppressionFile=true ile bir suppression dosyası üretip repository'ye koyabilirsin; dosya, hangi kırılmaları kabul ettiğinin yazılı kaydı olur. Yalnız şuna dikkat: validation hata verdiğinde dotnet pack 1 ile çıkıyor ama paket dosyası klasörde kalıyor. CI'da sonraki adım if: always() ile ya da hatayı yok sayan bir script'le çalışırsa kırık paket yine yayınlanabilir.
Yerel Bir Feed'e Push: Yayınlanan Sürüm Değiştirilemez
nuget.org'a geçmeden önce yayınlama davranışını yerel bir NuGet sunucusunda denedik. BaGetter, NuGet protokolünü konuşan küçük bir sunucu; Docker'da tek komutla açılıyor:
docker run -d --name relseries-nuget -p 127.0.0.1:18555:8080 \
-e ApiKey= -e Storage__Type=FileSystem -e Storage__Path=/data \
-e Database__Type=Sqlite -e "Database__ConnectionString=Data Source=/data/db.sqlite" \
bagetter/bagetter:latest
SDK 10'daki NuGet, HTTP üzerinden çalışan bir kaynağa push'u reddetti ve kaynağın allowInsecureConnections ile açıkça işaretlenmesini istedi. Yerel sunucu için bunu yalnız o kaynakta açan bir nuget.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="bookstore-local" value="http://localhost:18555/v3/index.json" allowInsecureConnections="true" />
</packageSources>
</configuration>
Aynı paketi iki kez gönderelim (API key uyarı satırlarını çıkardık):
$ dotnet nuget push Bookstore.Contracts.2.1.0.nupkg --source bookstore-local
Pushing Bookstore.Contracts.2.1.0.nupkg to 'http://localhost:18555/api/v2/package'...
PUT http://localhost:18555/api/v2/package/
Created http://localhost:18555/api/v2/package/ 230ms
Your package was pushed.
Pushing Bookstore.Contracts.2.1.0.snupkg to 'http://localhost:18555/api/v2/symbol'...
PUT http://localhost:18555/api/v2/symbol/
Created http://localhost:18555/api/v2/symbol/ 60ms
Your package was pushed.
$ dotnet nuget push Bookstore.Contracts.2.1.0.nupkg --source bookstore-local
Pushing Bookstore.Contracts.2.1.0.nupkg to 'http://localhost:18555/api/v2/package'...
PUT http://localhost:18555/api/v2/package/
Conflict http://localhost:18555/api/v2/package/ 18ms
To skip already published packages, use the option --skip-duplicate
error: Response status code does not indicate success: 409 (Conflict).
$ dotnet nuget push Bookstore.Contracts.2.1.0.nupkg --source bookstore-local --skip-duplicate
Conflict http://localhost:18555/api/v2/package/ 17ms
Package '.../Bookstore.Contracts.2.1.0.nupkg' already exists at feed 'http://localhost:18555/api/v2/package'.
İlk push Created, ikincisi 409 Conflict. nuget.org da aynı şekilde davranıyor: bir sürüm bir kez yayınlandıktan sonra içeriği değiştirilemiyor ve normalde silinemiyor; hatalı bir 2.1.0'ın düzeltmesi 2.1.1 olarak çıkıyor. --skip-duplicate, aynı workflow'un yeniden koşturulduğu durumlar için: zaten var olan paketi hata saymadan geçiyor. Bu güvenceyi her feed vermiyor. Klasör feed'ine aynı sürümü iki kez gönderdiğimizde:
$ dotnet nuget push artifacts/Bookstore.Contracts.2.1.0.nupkg --source "$PWD/artifacts/feed"
Pushing Bookstore.Contracts.2.1.0.nupkg to 'artifacts/feed'...
Your package was pushed.
$ dotnet nuget push artifacts/Bookstore.Contracts.2.1.0.nupkg --source "$PWD/artifacts/feed"
Pushing Bookstore.Contracts.2.1.0.nupkg to 'artifacts/feed'...
Your package was pushed.
İkinci push dosyanın üzerine yazdı. Klasör feed'leri test için pratik, ama ekipte paylaşılan bir feed olarak kullanıldığında "2.1.0" iki farklı içeriğe sahip olabilir ve iki geliştiricinin makinesinde farklı kod çalışır. Paylaşılan feed, sürümleri değiştirilemez tutan bir sunucu olmalı.
nuget.org'a Trusted Publishing
Klasik yöntemde nuget.org'da bir API key oluşturup CI'a secret olarak koyuyorsun. Bu key genelde uzun ömürlü; sızarsa biri senin adına paket yayınlayabilir. Trusted publishing bu anahtarı ortadan kaldırıyor: workflow çalışırken GitHub kısa ömürlü bir OIDC (OpenID Connect; kimlik bilgisini imzalı token'larla taşıyan standart) token'ı üretiyor, nuget.org bu token'ı doğrulayıp senin tanımladığın politikayla karşılaştırıyor ve eşleşirse bir saat geçerli, geçici bir API key veriyor. Her token tek bir key almak için kullanılabiliyor.
nuget.org tarafında politika, repository sahibini, repository adını, workflow dosyasının adını (yalnız dosya adı, publish-contracts.yml) ve isteğe bağlı olarak bir environment'ı içeriyor. Bookstore.Contracts'ın yayın workflow'u:
name: publish-contracts
on:
push:
tags: ['contracts/v*']
permissions:
contents: read
jobs:
publish:
runs-on: ubuntu-latest
environment: nuget
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-dotnet@v6
with:
global-json-file: global.json
- name: Find the previous release as baseline
id: baseline
run: |
previous=$(git describe --tags --abbrev=0 --match 'contracts/v*' "${GITHUB_REF_NAME}^" 2>/dev/null || true)
echo "version=${previous#contracts/v}" >> "$GITHUB_OUTPUT"
- name: Pack with package validation
env:
BASELINE: ${{ steps.baseline.outputs.version }}
run: |
args=()
if [ -n "$BASELINE" ]; then args+=("-p:PackageValidationBaselineVersion=$BASELINE"); fi
dotnet pack src/Bookstore.Contracts -c Release -o artifacts "${args[@]}"
- name: NuGet login (OIDC -> short-lived API key)
uses: NuGet/login@v1
id: login
with:
user: ${{ secrets.NUGET_USER }}
- name: Push to nuget.org
env:
NUGET_API_KEY: ${{ steps.login.outputs.NUGET_API_KEY }}
run: dotnet nuget push "artifacts/*.nupkg" --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json
Workflow, contracts/v* tag'i push edildiğinde çalışıyor; bu tag'i bir önceki yazıdaki release adımı atıyor. Önce baseline'ı buluyor: git describe ile tag'den önceki son contracts/v* tag'ini alıyor, ilk sürümde baseline yok. Sonra validation'lı pack, ardından NuGet/login ile geçici key ve push. Job seviyesindeki id-token: write izni, GitHub'ın bu job için OIDC token'ı üretmesine izin veriyor; workflow'un geri kalanı yalnız okuma izniyle çalışıyor. environment: nuget satırı, GitHub'da bu environment'a onay kuralı ekleyerek yayını bir insan onayına bağlamayı mümkün kılıyor; politikaya environment yazarsan başka bir job aynı workflow'dan yayın yapamıyor. Dokümana göre private repository'lerden oluşturulan politikalar ilk başarılı yayına kadar yedi gün geçici olarak aktif kalıyor. GitHub Actions'ta OIDC'nin genel mekaniğini GitHub Actions serisinin "GitHub Actions ile Deploy 1: OIDC ile Azure App Service ve Şifresiz Cloud Erişimi" yazısında anlatmıştık. Bu workflow actionlint ile doğrulandı; GitHub'da ve nuget.org'da koşulmadı.
Prerelease, Unlist, Deprecate ve Vulnerability
Yayından sonra paketin yaşam döngüsünü yöneten dört araç var. Prerelease sürümler (2.2.0-rc.1) kullanıcı açıkça istemedikçe seçilmiyor; Visual Studio'da "Include prerelease" işaretlenmeden görünmüyor. Kırıcı bir major'ı önce rc olarak yayınlayıp birkaç iç kullanıcıyla denemek iyi bir alışkanlık.
Unlist, bir sürümü arama sonuçlarından gizliyor ama silmiyor: o sürümü tam olarak referans eden projeler restore etmeye devam ediyor. Deprecate ise sürümün kullanıcılarına bilgi veriyor. nuget.org'da üç sebep seçilebiliyor: artık bakımı yapılmıyor (Legacy), kritik hatası var ve diğer; yanına alternatif bir paket önerilebiliyor. Kullanıcı bunu Visual Studio'nun Installed sekmesinde ya da dotnet list package --deprecated çıktısında görüyor. İkisi birlikte de kullanılabiliyor: kritik hatalı bir sürümü hem unlist edip hem de deprecate etmek, yeni kullanıcıların onu seçmesini engelliyor, mevcut kullanıcılara da sebebi söylüyor.
Vulnerability bilgisi ise nuget.org'a GitHub Advisory Database'den geliyor. Paketinde bir güvenlik açığı bulduğunda bir advisory yayımlıyorsun; NuGet'in restore sırasındaki audit'i, etkilenen sürümü kullanan her projede önem derecesine göre NU1901 ile NU1904 arasında bir uyarı veriyor. Güvenlik yaması çıkarırken bu bilginin doğru sürüm aralığını göstermesi, kullanıcının "etkileniyor muyum?" sorusunun cevabı.
Üretimde Dikkat
Paket kimliğini koru. nuget.org'da bir organizasyon hesabı aç ve paketleri onun altında yayınla; tek bir kişinin hesabına bağlı paket, o kişi ayrıldığında sahipsiz kalır. Bir önek (ör. Bookstore.) için ID prefix reservation başvurusu yaparsan başkası bu önekle paket yayınlayamaz ve paketlerin doğrulanmış işaretiyle görünür.
Yayını tek bir yoldan yap. Paket yalnız tag'den tetiklenen workflow'dan çıkmalı; bir geliştiricinin kendi makinesinden dotnet nuget push yapabilmesi, release sürecinin bütün kontrollerini (validation, onay, changelog) atlamak demek. Trusted publishing bunu doğal olarak zorluyor, çünkü yayın yetkisi bir kişide değil, belirli bir workflow'da.
Baseline'ı otomatik bul. Baseline'ı elle güncellemek unutulur ve validation hep eski bir sürümle karşılaştırma yapar. Workflow'daki git describe adımı bunu tag'den çıkarıyor.
Symbol paketini ve Source Link'i kontrol et. NuGet Package Explorer gibi bir araçla ya da nuget.info'da paketin repository bilgisinin ve commit'inin dolu olduğunu, pdb'nin snupkg'de bulunduğunu doğrula; eksikse kullanıcıların debugger'ı kaynağa inemez.
Sık Düşülen Tuzaklar
Aynı sürümü yeniden push'lamaya çalışmak. 409 hatası bir bug değil, garanti. Hatalı paketi düzeltmenin yolu yeni bir patch sürümü ve eskisini unlist ya da deprecate etmek.
İsteğe bağlı parametreyi uyumlu sanmak. Tahmin bölümünde gördüğümüz gibi kaynak uyumlu ama binary kırıcı. Constructor ve method imzalarına ekleme yapmak yerine overload ya da property ekle; emin değilsen package validation'a sor.
Sürüm aralığı ve sabit sürüm tercihini düşünmeden yapmak. PackageReference'ta Version="2.0.0" "en az 2.0.0" demek ve NuGet koşulu sağlayan en düşük sürümü seçiyor; 2.* gibi floating bir sürüm ise her restore'da en yenisini alıyor ve build'i tekrarlanamaz yapıyor. Uygulamalarda sabit sürüm ve lock dosyası, library'lerde ise bağımlılıklar için alt sınır yeterli; NuGet dokümanı da sahibi olmadığın paketlere üst sınır koymamayı öneriyor.
Private bir paketi yanlışlıkla nuget.org'a göndermek. dotnet nuget push'a --source vermezsen varsayılan push kaynağı kullanılır; makinedeki config'e göre bu nuget.org olabilir. İç paketler için --source'u her zaman açıkça yaz, repository'nin nuget.config'inde defaultPushSource'u iç feed'e ayarla ve nuget.org'a yayın yetkisini yalnız trusted publishing politikası olan workflow'lara ver.
Validation hatasından sonra kalan paketi yayınlamak. dotnet pack hata verse de .nupkg klasörde kalıyor; push adımını yalnız pack başarılıysa çalıştır.
Küçük Bir Deneme
★☆☆ Bookstore.Contracts'ı paketle ve .snupkg'nin içini aç. pdb dosyası nerede, Source Link JSON'u içinde mi?
★★☆ Money'nin Currency property'sini CurrencyCode olarak yeniden adlandır ve 2.1.0'ı baseline alarak paketle. Hangi hata kodlarını görüyorsun? Ardından ApiCompatGenerateSuppressionFile ile suppression dosyası üret ve dosyanın içeriğini incele.
★★★ BaGetter container'ını açıp Bookstore API'sini ProjectReference yerine PackageReference ile Contracts 2.1.0'a bağla. Feed'e 2.1.1 koyduğunda Version="2.1.0", Version="[2.1.0]" ve Version="2.*" için hangi sürümün çözüldüğünü dotnet list package ile kontrol et.
Contracts paketi artık doğrulanmış biçimde ve anahtarsız yayınlanıyor. Bir sonraki yazıda aynı işi frontend tarafında yapıyoruz: bookstore-web'deki ortak component'lerden bir Angular kütüphanesi çıkarıp ng-packagr ile paketliyor, peerDependencies, dist-tag'ler ve npm trusted publishing ile yayınlıyoruz.