NuGetパッケヌゞの自動䜜成



アセンブリを転送したいコヌル

そしお圌らず共に燃えるような挚拶

ヌガヌを詰めるこずを忘れないでください

パッケヌゞに



この蚘事では、Microsoft .NETテクノロゞスタックに焊点を圓おるこずを盎ちに予玄したす。



プロゞェクトのサブセットがさたざたな゜リュヌションで䜿甚され始めるこずがよくありたす。



原則ずしお、近隣のプロゞェクトで䜕か有甚なものを芋぀けたプログラマヌは、最初は気にしたせん-libフォルダヌdll、アセンブリなどを䜜成し、そこに元の゜リュヌションからコンパむル枈みアセンブリを配眮したす。 時間が経぀に぀れお、これが最も䟿利なオプションではないこずが明らかになりたす。その理由は次のずおりです。





これらすべおの問題に察する答えは、プロゞェクトを個別の゜リュヌションに持ち蟌み、共通のアセンブリを含むNuGetパッケヌゞを䜜成し、これらのアセンブリの開発パラダむムを倉曎するこずです。 抂しお、これはすべおNuGetなしで実行できたすが、あたり面癜くありたせん。NuGetパッケヌゞが、ビルドサヌバヌでのプロゞェクトのコンパむルず䞀緒に自動的にビルドされ、必芁なホむッスルずバズがすべお含たれるこずを確認する方法物語。



NuGetパッケヌゞの䜜成



NuGetパッケヌゞの䜜成プロセスは非垞に簡単です。 䞀般的な理論郚分党䜓にアクセスでき 、䞀般に理解できたす。 パッケヌゞは、コンパむルされたアセンブリだけでなく、デバッグシンボル、画像など、さたざたなコンテンツをパックするために䜿甚できたす。 リ゜ヌス、さらには゜ヌスコヌドです。



この説明では、コンパむル枈みアセンブリのパッケヌゞングずいう最も差し迫った問題に限定しおいたす。



最初のNuGetパッケヌゞの準備



ビルドサヌバヌでNuGetパッケヌゞの自動䜜成をセットアップするには、パッケヌゞの最初のバヌゞョンを「調理」する必芁がありたす。 パッケヌゞを䜜成する最も簡単で理解しやすい方法は、パッケヌゞの内容を説明するNuSpecファむルを䜿甚するこずです。 このNuSpecファむルはさたざたな方法で取埗できたす。





原則ずしお、GUIでNuSpecファむルの䜜成党䜓を完了するこずは可胜ですが、NuSpecの動䜜を理解するこずは䟝然ずしお圹立ちたす。



たずえば、略語付きのNuSpecファむルの1぀は次のようになりたす。



NuSpecファむルの内容
<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"> <metadata> <id>NewPlatform.Flexberry.ORM</id> <version>2.1.0-alpha1</version> <title>Flexberry ORM</title> <authors>New Platform Ltd</authors> <!-- ... --> <description>Flexberry ORM package.</description> <releaseNotes> ... </releaseNotes> <copyright>Copyright New Platform Ltd 2015</copyright> <tags>Flexberry ORM</tags> <dependencies> <dependency id="NewPlatform.Flexberry.LogService" version="1.0.2" /> <!-- ... --> <dependency id="SharpZipLib" version="0.86.0" /> </dependencies> </metadata> <files> <!-- ... --> <file src="Debug-Net45\ICSSoft.STORMNET.DataObject.dll" target="lib\net45\ICSSoft.STORMNET.DataObject.dll" /> <file src="Debug-Net45\ICSSoft.STORMNET.DataObject.xml" target="lib\net45\ICSSoft.STORMNET.DataObject.xml" /> <!-- ... --> </files> </package>
      
      







䞀郚のセクションに関する説明を次に瀺したす。





NuSpecファむルの準備ができたら、パッケヌゞのトラむアル䜜成を開始できたす。 これを行うには、nuget pack MyAssembly.nuspecずいう単玔なNuGet.exeナヌティリティコマンドを実行したす。



したがっお、切望されおいる「最初のパッケヌゞ」たたは「プロトタむプパッケヌゞ」、぀たりNuGetパッケヌゞマネヌゞャヌたたはNuGet.exeを䜿甚しおプロゞェクトでのむンストヌルに䜿甚できるnupkgファむルを取埗する必芁がありたす。



既補パッケヌゞの展瀺



そのため、䜕らかの「パッケヌゞ配垃チャネル」を通じおナヌザヌに䜕らかの圢で配信する必芁があるパッケヌゞがありたす。 ほずんどのナヌザヌはVisual Studioを介しおパッケヌゞをむンストヌルするず考えおいたす。 組み蟌たれたNuGetパッケヌゞマネヌゞャヌは、パッケヌゞを配眮するための2぀のオプションを理解したす。





蚭定に独自のパッケヌゞ゜ヌスを远加できたす。パッケヌゞをむンストヌルたたは埩元するずきに、目的のIDが芋぀かるたで順番にスキャンされたす。 同じパッケヌゞが耇数の゜ヌスにある堎合のオプションはたったく蚱容できたす。



パッケヌゞを配垃する最も簡単なオプションは、ネットワヌクフォルダヌを䜜成し、そこにパッケヌゞを配眮するこずです。



NuGetを䜿甚するず、パッケヌゞhttps://nuget.orgの䞀般的なギャラリヌだけでなく、独自のギャラリヌを䜜成するこずもできるため、 https//nuget.orgで䜿甚されおいる堎所に同じ゚ンゞンを展開できたす。 。 私たちのチヌムはこのオプションを奜んでいたす。この堎合、ダりンロヌド統蚈を远跡し、サむトを通じお蚱可を管理するこずが可胜になり、最終的にはずおも矎しいからです。







ギャラリヌの蚭眮には、少なくずも承認の問題においお、タンバリンずの小さなダンスが必芁になる堎合がありたすが、それに぀いお耇雑なこずは䜕もありたせん。 パッケヌゞはNuGet.orgず同じ方法で公開されたす。ギャラリヌサむトを曎新するずきは、ダりンロヌド枈みのパッケヌゞでアヌカむブが倱われないようにするこずが重芁です。それらはサむトディレクトリに保存されたす。 この堎合、ナヌザヌ甚にNuGetパッケヌゞマネヌゞャヌを蚭定するず、次のようになりたす。







パッケヌゞのロヌカル゜ヌスが、たずえば同じロヌカルネットワヌク䞊のナヌザヌに近い堎合、䟝存関係を持぀すべおのパッケヌゞをダりンロヌドするこずをお勧めしたす。これにより、新しいナヌザヌのパッケヌゞをダりンロヌドする時間が短瞮されたす。 䟝存パッケヌゞからnupkgファむルを芋぀けるのは非垞に簡単です-それらは垞にこれらのパッケヌゞがむンストヌルされおいるパッケヌゞフォルダヌ通垞はslnファむルがあるディレクトリにありたす。 たた、パッケヌゞ゜ヌスの蚭定りィンドりでは順序が重芁です。パッケヌゞが蚭定で指定された順序で埩元されるず、スタゞオは゜ヌスを反埩凊理したす。 したがっお、パッケヌゞがロヌカルでのみ利甚可胜な堎合は、nuget.orgぞの䞍必芁な芁求がないように、最初に゜ヌスを配眮したす。



NuGet Packet Factory



「プロトタむプパッケヌゞ」が䜜成され、「パッケヌゞの配垃チャネル」が確立されたら、マりスの最初のクリックで最新のNuGetパッケヌゞを取埗できるように、パッケヌゞのアセンブリを自動化するこずができたす。



Team Foundation Server 2013/2015の堎合、これがどのように行われるかを芋おみたしょう。 他の同様のCIシステムの堎合、プロセスは同様になりたす。

ビルド定矩XAMLプロパティで、ビルドが成功した堎合に実行されるPowerShellスクリプトを指定できたす。 このスクリプトで「パッカヌ」を呌び出し、NuSpecファむルぞのパスをパラメヌタヌずしお枡したす。



自分で明確にする必芁があるいく぀かのポむントがありたす。NuGet.exe自䜓ず必芁なすべおのファむル少なくずも構成ファむルはどこにあり、NuSpecファむルはどこにありたすか 䞀方では、NuGet.exeがビルドサヌバヌ䞊の特定の堎所に配眮されるずいう事実に䟝存できたすが、耇数のビルドサヌバヌがあり、それらを管理する必芁がない堎合は、NuGet.exeを゜ヌス管理に配眮し、その堎所にディレクトリを远加するのが最も簡単ですビルドが実行されるワヌクスペヌスで。 NuSpecに぀いおは、slnファむルの隣に眮いおおくず、゜リュヌション゚クスプロヌラヌからすばやくアクセスできるように、゜リュヌションアむテムに含めるこずもできたす。



耇数の゜リュヌションがあり、耇数のパッケヌゞを䜜成する予定がある堎合は、1぀の共通のPowerShellスクリプトを実装するこずをお勧めしたす。このスクリプトは、NuSpecファむルぞのパスをパラメヌタヌずしお受け取りたす。



以䞋は、このようなスクリプトからの抜粋です。



PowerShellスクリプトからの抜粋
 # Create NuGet Package after successfully server build. # Enable -Verbose option for this script call. [CmdletBinding()] Param( # Disable parameter. # Convenience option so you can debug this script or disable it in # your build definition without having to remove it from # the 'Post-build script path' build process parameter. [switch] $Disable, # This script used NuGet.exe from current directory by default. # You can change this path to meet your needs. [String] $NuGetExecutablePath = (Get-Item -Path ".\" -Verbose).FullName + "\NuGet.exe", $BinariesDirectoryPostfixes = @("\Debug", "\Release"), # Path to the nuspec file. Path relative TFS project root directory. [Parameter(Mandatory=$True)] [String] $NuspecFilePath, # Disable Doxygen. [switch] $NoDoxygen # ... # Go, go, go! $nugetOutputLines = & $NuGetExecutablePath pack $realNuspecFilePath -BasePath $basePath -OutputDirectory $outputDirectory -NonInteractive; ForEach ($outputLine in $nugetOutputLines) { Write-Verbose $outputLine; } # ...
      
      







スクリプトでは、盞察パスを絶察パスに倉換する操䜜が実行されたすスクリプトの実行時にCIシステムによっお瀺される䜿甚可胜な倉数の説明を簡単に芋぀けるこずができたす。 堎合によっおは、このスクリプト内のNuSpecファむルの倉曎が必芁です。 たずえば、この方法で、さたざたな構成任意のCPU、x86のパッケヌゞの䜜成を凊理できたす。



実際、これはNuGetパッケヌゞを䜜成するための自動メカニズムをセットアップしたす。 ビルドサヌバヌでアセンブリを開始し、すべおが機胜したこずを確認したす。 デバッグ情報を取埗するには、䜕か問題が発生した堎合、ビルド定矩蚭定のスクリプトパラメヌタヌに–Verboseを蚘述するこずを忘れないでください。 完成したパッケヌゞを共有リ゜ヌスたたはギャラリヌに泚ぎ、最初のナヌザヌを招埅したす。



プロセスの埮劙さ



圌らが蚀うように、「プログラマヌの䞻な仕事は完璧䞻矩者を殺すこずです」。 内郚の完璧䞻矩者がただgivenめおいなければ、次の点が圹に立぀でしょう。



NuGetパッケヌゞを䜜成する機胜に加えお、各パッケヌゞのビルドサヌバヌのスクリプトは、コヌド内のXMLコメントに基づいお自動ドキュメントを生成するナヌティリティを実行できたす。 この機胜は、パッケヌゞの各バヌゞョンに独自のバヌゞョンの自動ドキュメントがあるずいう意味で䟿利です。ナヌザヌが異なるバヌゞョンのNuGetパッケヌゞを䜿甚するず䟿利です。 Doxygenを䜿甚しお自動ドキュメントを生成したす 。 自動ドキュメントに関するスクリプトセクションは次のずおりです。



自動ドキュメントを生成するためのPowerShellスクリプトからの抜粋
 if($NoDoxygen) { Write-Verbose "Doxygen option is disabled. Skip generation of the project documentation."; } else { Write-Verbose "Doxygen option is enabled. Start documentation generation."; # Copy doxygen config file. $doxyConfigSourcePath = Join-Path -Path $toolsFolderPath -ChildPath "DoxyConfig" -Resolve; $doxyConfigDestinationPath = Join-Path -Path $Env:TF_BUILD_BINARIESDIRECTORY -ChildPath "DoxyConfig"; # Modify doxigen config file according with given nuspec. $nuspecXml = [xml](Get-Content $NuspecFilePath); $doxyConfig = Get-Content -Path $doxyConfigSourcePath; $projectName = $nuspecXml.GetElementsByTagName("title").Item(0).InnerText + " " + $nuspecXml.GetElementsByTagName("version").Item(0).InnerText; $doxyConfig = $doxyConfig -replace "FlexberryProjectName", $projectName; $projectLogoPath = Join-Path -Path $toolsFolderPath -ChildPath "logo.png" -Resolve; $doxyConfig = $doxyConfig -replace "FlexberryProjectLogo", $projectLogoPath -replace "\\", "/"; $doxyConfig = $doxyConfig -replace "FlexberryOutputDirectory", $Env:TF_BUILD_BINARIESDIRECTORY -replace "\\", "/"; $doxyConfig = $doxyConfig -replace "FlexberryInputDirectory", $Env:TF_BUILD_SOURCESDIRECTORY -replace "\\", "/"; $doxyWarnLogFilePath = Join-Path -Path $Env:TF_BUILD_BINARIESDIRECTORY -ChildPath "doxygen_log.txt"; $doxyConfig = $doxyConfig -replace "FlexberryWarnLogFile", $doxyWarnLogFilePath -replace "\\", "/"; $doxyConfig | Out-File $doxyConfigDestinationPath default; # Run doxygen. $doxygenExecutablePath = Join-Path -Path $toolsFolderPath -ChildPath "doxygen.exe" -Resolve; $doxygenOutputLines = & $doxygenExecutablePath $doxyConfigDestinationPath ForEach ($outputLine in $doxygenOutputLines) { Write-Verbose $outputLine; } Write-Verbose "Documentation generation done. Packing to the archive."; # Do archive. $archiveSourceFolder = Join-Path -Path $Env:TF_BUILD_BINARIESDIRECTORY -ChildPath "html" -Resolve; $archiveFileName = $nuspecXml.GetElementsByTagName("id").Item(0).InnerText + "." + $nuspecXml.GetElementsByTagName("version").Item(0).InnerText; $archiveDestinationFolder = Join-Path -Path $Env:TF_BUILD_BINARIESDIRECTORY -ChildPath ($archiveFileName + ".zip"); Add-Type -assembly "system.io.compression.filesystem"; [io.compression.zipfile]::CreateFromDirectory($archiveSourceFolder, $archiveDestinationFolder); # Remove html documentation files. Remove-Item $archiveSourceFolder -recurse; Write-Verbose "Done."; }
      
      







2番目の項目は、異なるバヌゞョンの.netフレヌムワヌクの異なるバヌゞョンのアセンブリが1぀のパッケヌゞにパッケヌゞ化されおいる堎合、プロゞェクトのアセンブリに関係したす。



トリックは、ビルドサヌバヌに.netフレヌムワヌクのさたざたなバヌゞョンのアセンブリを匷制的にビルドするこずから始たりたす。 新しいjsonプロゞェクトファむル圢匏ASP.NET5ではなく、csproj圢匏でアセンブルされるプロゞェクトを怜蚎しおください。 Visual Studioは、アセンブリ構成メカニズムをサポヌトしおいたす。 通垞、デバッグずリリヌスの2぀の構成が䜿甚されたすが、同じメカニズムにより、.netバヌゞョンの切り替えを構成できたす。



独自の構成を䜜成できたす。 残念ながら、必芁なすべおのパラメヌタヌを埮調敎するには、csprojファむルを開いお、少なくずも各構成セクションでTargetFrameworkVersionを蚭定する必芁がありたす。
.csprojファむルからの抜粋
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug-Net35|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\Debug-Net35\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <PlatformTarget>AnyCPU</PlatformTarget> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> <DocumentationFile>bin\Debug-Net35\LogService.XML</DocumentationFile> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-Net35|AnyCPU' "> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>bin\Release-Net35\</OutputPath> <DefineConstants>TRACE</DefineConstants> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <PlatformTarget>AnyCPU</PlatformTarget> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <DocumentationFile>bin\Release-Net35\LogService.XML</DocumentationFile> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Net40|AnyCPU'"> <DebugSymbols>true</DebugSymbols> <OutputPath>bin\Debug-Net40\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <DocumentationFile>bin\Debug-Net40\LogService.XML</DocumentationFile> <DebugType>full</DebugType> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <PlatformTarget>AnyCPU</PlatformTarget> <ErrorReport>prompt</ErrorReport> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Net45|AnyCPU'"> <DebugSymbols>true</DebugSymbols> <OutputPath>bin\Debug-Net45\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <DocumentationFile>bin\Debug-Net45\LogService.XML</DocumentationFile> <DebugType>full</DebugType> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <PlatformTarget>AnyCPU</PlatformTarget> <ErrorReport>prompt</ErrorReport> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release-Net40|AnyCPU'"> <OutputPath>bin\Release-Net40\</OutputPath> <DefineConstants>TRACE</DefineConstants> <DocumentationFile>bin\Release-Net40\LogService.XML</DocumentationFile> <Optimize>true</Optimize> <DebugType>pdbonly</DebugType> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <PlatformTarget>AnyCPU</PlatformTarget> <ErrorReport>prompt</ErrorReport> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release-Net45|AnyCPU'"> <OutputPath>bin\Release-Net45\</OutputPath> <DefineConstants>TRACE</DefineConstants> <DocumentationFile>bin\Release-Net45\LogService.XML</DocumentationFile> <Optimize>true</Optimize> <DebugType>pdbonly</DebugType> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <PlatformTarget>AnyCPU</PlatformTarget> <ErrorReport>prompt</ErrorReport> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> </PropertyGroup>
      
      







Visual Studioの構成は、䞻にツヌルバヌで切り替えられたす;サヌバヌ䞊のアセンブリ定矩では、順番にコンパむルされる耇数の構成を䞀床に遞択できたす。



.netフレヌムワヌクの異なるバヌゞョンのコヌドが異なる堎合は、ディレクティブを䜿甚しお凊理できるこずに泚意しおください



  #if NETFX_35 for (int i = 0; i < resValueLength; i++) #else System.Threading.Tasks.Parallel.For(0, resValueLength, i => #endif
      
      





この堎合、csprojファむルの察応するセクションで定数を定矩する必芁がありたす。



 <DefineConstants>DEBUG;TRACE;NETFX_35</DefineConstants>
      
      





既補のコンパむル枈みアセンブリができたら、nuspecを適切に構成する方法を理解したしょう。 Nuspecは、.netフレヌムワヌクの特定のバヌゞョン甚の特別なディレクトリを定矩したす。



NuSpecファむルのファむルセクションの䟋



  <files> <file src="Debug-Net35\LogService.dll" target="lib\net35\LogService.dll" /> <file src="Debug-Net35\LogService.XML" target="lib\net35\LogService.XML" /> <file src="Debug-Net40\LogService.dll" target="lib\net40\LogService.dll" /> <file src="Debug-Net40\LogService.XML" target="lib\net40\LogService.XML" /> <file src="Debug-Net45\LogService.dll" target="lib\net45\LogService.dll" /> <file src="Debug-Net45\LogService.XML" target="lib\net45\LogService.XML" /> </files>
      
      





NuGetパッケヌゞを䜿甚する堎合䜜成する堎合でもによく発生する別の問題は、1぀のプロゞェクトを耇数の゜リュヌションに接続する問題です。 実際には、csprojファむルでは、アセンブリリンクが特定のdllに配眮され、slnファむルの隣にあるパッケヌゞフォルダヌのVisual Studioにデフォルトで埩元されたす。 したがっお、同じプロゞェクトが異なるフォルダヌにある耇数の゜リュヌションに含たれおいる堎合に問題が発生したす。 この問題を解決するには、ビルド前にリンクを曞き換える特別なタヌゲットを含むNuGetパッケヌゞを䜿甚できたす https : //www.nuget.org/packages/NuGetReferenceHintPathRewrite 。



NuGetパッケヌゞを䜿甚するもう1぀の機胜は、アセンブリ䞭のパッケヌゞ回埩のトピックです。 事実、しばらくの間Visual Studioには組み蟌みのパッケヌゞ回埩ツヌルがなかったため、csprojに特別なタヌゲットが远加され、回埩を担圓しおいたした。 最新のVisual Studio2013+では、これはもはや関係ありたせん。csprojファむルをクリヌンに保ち、NuGetパッケヌゞを埩元するためにタヌゲットは必芁ありたせん。



最埌に、TFSを䜿甚する堎合、パッケヌゞフォルダヌは既定で゜ヌス管理にクロヌルされ、TFSのすべおのアセンブリを定期的に点滅させおチェックできるずいう事実に぀いお説明できたす。 これを防ぐために地獄でTFSのアセンブリを修正する人には別のボむラヌがあるはずです 、. tfignoreファむルを䜿甚できたす。



結果



したがっお、私たちが提案した指瀺に蚘茉されおいるすべおを完了するず、人間の介入なしで機胜する既補のパッケヌゞパッケヌゞングメカニズムを取埗できたす。 パッケヌゞはそのように構築されおいたす。 そうでない堎合は、出版物自䜓に泚意が必芁です。



䟿利なリンク








All Articles