Tworzenie paczek nuget – część 1: pakowanie

Zastanawiałeś się kiedyś jak właściwie tworzy się uwielbiane przez wszystkich paczki .nuget? Każdy dobrze wie jak je pobrać i jak ich używać, ale jak ją stworzyć? Dowiesz się tego w tym wpisie!

Przykładowy projekt

Tworzenie paczek .nuget omówimy na przykładzie nowej biblioteki – ConfigReadera – która pozwala na odczytywanie konfiguracji z pliku w postaci JSONowej lub klucz-wartość.

JSON

{
    "TestKey": "TestValue",
    "TestInt": 1,
    "TestDouble": 1.1
}

klucz:wartość\n

TestKey:TestValue
TestInt:1
TestDouble:1.1

Rozwiązanie podzielone jest na 3 projekty:

  • ConfigReader.Contract – z interfejsem ConfigReadera. Ten projekt opublikujemy jako osobną paczkę nuget.
  • ConfigReader.Helper – z pomocniczymi metodami. Tego projektu nie będziemy publikowali osobno.
  • ConfigReader.Implementations – z implementacją ConfigReadera (zawiera referencje do pozostałych dwóch projektów i paczki Newtonsoft.Json) Ten projekt opublikujemy tak, aby zawierał referencje do paczek nuget: parsera json i .Contract, a jednocześnie posiadał w sobie DLLkę helpera.
    Kod projektu, który będziemy pakować

Przygotowanie projektu

Na początek musimy zaopatrzyć się w plik nuget.exe. Możemy go pobrać z nuget.org lub dodać paczkę nuget NuGet.CommandLine do projektów w Package Manager Console:

Install-Package NuGet.CommandLine

Ja wybrałem tą drugą opcje.

Następnie utworzymy plik .nuspec. Przechodzimy najpierw do folderu z plikiem .csproj, z którego chcemy utworzyć paczkę .nuget, a następnie wpisujemy komendę:

nuget spec

W rezultacie otrzymujemy taki plik:

<?xml version="1.0"?>
<package >
 <metadata>
 <id>$id$</id>
 <version>$version$</version>
 <title>$title$</title>
 <authors>$author$</authors>
 <owners>$author$</owners>
 <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
 <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
 <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
 <requireLicenseAcceptance>false</requireLicenseAcceptance>
 <description>$description$</description>
 <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
 <copyright>Copyright 2017</copyright>
 <tags>Tag1 Tag2</tags>
 </metadata>
</package>

Plik ten opisuje naszą paczkę. Są tam metadane opisujące między innymi nazwę paczki, autorów ikonkę, tagi. To tutaj ustawia się też zależności do innych paczek/projektów i reguły załączania dodatkowych plików do projektu. Większość ustawień jest tutaj opcjonalna, jedyne tagi które musimy wypełnić to:

  • id – nazwa paczki Np NuGet.CommandLine
  • version – wersja paczki podana w formacie 1.0.0 , może zawierać suffixy (na podstawie suffixów nuget rozpoznaje czy paczka jest pre-release)
  • description – opis paczki
  • authors – autorzy projektu, rozdzieleni przecinkami

Jak widać wyżej, możemy używać zmiennych. Podczas pakowania projektu nuget zamienia wszystkie symbole pomiędzy znakami $ $. Zmienne ustalane są w trakcie pakowania projektu. Są one brane są na z dwóch źródeł. Pierwsze źródło to parametry ustawiane przy pakowaniu.

nuget pack -properties <name>=<value>;<name>=<value>

Drugie źródło to zmienne automatyczne ustawiane na podstawie informacji dllki, głównie z AssemblyInfo.cs. Np. $id$,$version$. Więcej o zmiennych tutaj

Pakowanie

Projekt możemy spakować na dwa sposoby.

Pierwszym z nich jest przejście do folderu z projektem zawierającym plik .nuspec i wywołać komendę pakowania.

cd .\src\ConfigReader.Contract
nuget pack

Drugim sposobem, często wykorzystywanym z systemami continus delivery (CD), jest pakowanie z podaniem ścieżki  do katalogu z projektem i podaniem katalogu do którego ma zostać skopiowany plik .nuget.

nuget pack .\src\ConfigReader.Implementations\ 
	-OutputDirectory .\dist\  
	-Prop Configuration=Release

Możemy teraz taką paczkę podejrzeć przez Nuget Package Explorer. Jak przejrzymy paczkę ConfigReader.Implementations zobaczymy, że automatycznie wykryte zostały zainstalowane w projekcie paczki i załączona została referencja do Newtonsoft.Json . Pominięte zostało NuGet.CommandLine, która jest jedynie zależnością deweloperską. Brakuje jednak zależności do ConfigReader.Contract i nie jest dołączona dllka Helperów – trzeba to poprawić ręcznie w pliku .nuspec

Aby dołączyć dodatkowe dllki wystarczy dodać do .nuspec

<?xml version="1.0"?>
<package>
 <metadata>
 ...
 </metadata>
 <files>
 <file src="bin\$configuration$\ConfigReader.Helper.dll" target="lib\net452\" />
 </files>
</package>

Można użyć bardziej ogólnych zasad dołączania dllek, ale nie chciałem w tym miejscu dołączać wszystkich dllek znajdujących się w katalogu bin\ (np. Newtonsoft.Json, ConfigReader.Contract). Więcej można poczytać tutaj

Aby dodać zależność do innych paczek nuget, które nie są w pliku packages.config, trzeba uzupełnić plik .nuspec o:

<?xml version="1.0"?>
<package>
 <metadata>
 ...
 <dependencies>
 <dependency id="ConfigReader.Contract" version="[$version$]" />
 </dependencies>
 </metadata>
</package>

Numer wersji można podać w kilku postaciach:

  • 1.0 – podanie minimalnej wersji (1.0 < x)
  • [1.0,2.0], (1.0,2.0), [1.0,2.0) – podanie zakresu od do. Nawias kwadratowy oznacza że numer wersji jeszcze wchodzi do zakresu. Nawiasy można mieszać
  • (1.0,), (,1.0), (,1.0] – Podobnie jak wyżej, ale z podaniem tylko górnej lub dolnej wersji.
  • [1.0] – Podanie dokładnej wersji

Więcej o tym można przeczytać tutaj

Ciąg dalszy

W następnej części wpisu omówimy:

  • jak opublikować paczkę
  • jak działają feedy lokalne i http
  • opowiemy o wersjonowaniu paczek
  • pokażemy konfigurację kilku znanych systemów CI (TC, AppVeyor)

One Pingback/Trackback

    11 September 2017 at 2:09pm
    Tworzenie paczek nuget – część 1: pakowanie – ...
  • dotnetomaniak.pl
  • Mateusz Chodkowski

    Dzięki za zebranie tego w całość! 🙂

  • Pingback: dotnetomaniak.pl()