Bagikan melalui


Memahami Proses Build

oleh Jason Lee

Topik ini menyediakan panduan proses pembangunan dan penyebaran skala perusahaan. Pendekatan yang dijelaskan dalam topik ini menggunakan file proyek Microsoft Build Engine (MSBuild) kustom untuk memberikan kontrol mendetail atas setiap aspek proses. Dalam file proyek, target MSBuild kustom digunakan untuk menjalankan utilitas penyebaran seperti Alat Penyebaran Web (MSDeploy.exe) Internet Information Services (IIS) dan utilitas penyebaran database VSDBCMD.exe.

Catatan

Topik sebelumnya, Memahami File Proyek, menjelaskan komponen utama file proyek MSBuild dan memperkenalkan konsep file proyek terpisah untuk mendukung penyebaran ke beberapa lingkungan target. Jika Anda belum terbiasa dengan konsep-konsep ini, Anda harus meninjau Memahami File Proyek sebelum Anda mengerjakan topik ini.

Topik ini merupakan bagian dari serangkaian tutorial berdasarkan persyaratan penyebaran perusahaan dari perusahaan fiktif bernama Fabrikam, Inc. Seri tutorial ini menggunakan solusi sampel— solusi Contact Manager—untuk mewakili aplikasi web dengan tingkat kompleksitas yang realistis, termasuk aplikasi ASP.NET MVC 3, layanan Windows Communication Foundation (WCF), dan proyek database.

Metode penyebaran di jantung tutorial ini didasarkan pada pendekatan file proyek terpisah yang dijelaskan dalam Memahami File Proyek, di mana proses build dikendalikan oleh dua file proyek—satu berisi instruksi build yang berlaku untuk setiap lingkungan tujuan, dan satu berisi pengaturan build dan penyebaran khusus lingkungan. Pada waktu build, file proyek khusus lingkungan digabungkan ke dalam file proyek agnostik lingkungan untuk membentuk serangkaian instruksi build lengkap.

Gambaran Umum Build dan Penyebaran

Dalam solusi Contact Manager, tiga file mengontrol proses build dan penyebaran:

  • File proyek universal (Publish.proj). Ini berisi instruksi build dan penyebaran yang tidak berubah di antara lingkungan tujuan.
  • File proyek khusus lingkungan (Env-Dev.proj). Ini berisi pengaturan build dan penyebaran yang khusus untuk lingkungan tujuan tertentu. Misalnya, Anda dapat menggunakan file Env-Dev.proj untuk menyediakan pengaturan bagi pengembang atau lingkungan pengujian dan membuat file alternatif bernama Env-Stage.proj untuk menyediakan pengaturan untuk lingkungan penahapan.
  • File perintah (Publish-Dev.cmd). Ini berisi perintah MSBuild.exe yang menentukan file proyek mana yang ingin Anda jalankan. Anda dapat membuat file perintah untuk setiap lingkungan tujuan, di mana setiap file berisi perintah MSBuild.exe yang menentukan file proyek khusus lingkungan yang berbeda. Ini memungkinkan pengembang menyebarkan ke lingkungan yang berbeda hanya dengan menjalankan file perintah yang sesuai.

Dalam solusi sampel, Anda dapat menemukan ketiga file ini di folder Terbitkan solusi.

Dalam solusi sampel, Anda dapat menemukan tiga file di folder Terbitkan solusi.

Sebelum Anda melihat file-file ini secara lebih rinci, mari kita lihat cara kerja proses build keseluruhan saat Anda menggunakan pendekatan ini. Pada tingkat tinggi, proses build dan penyebaran terlihat seperti ini:

Seperti apa proses build dan penyebaran pada tingkat tinggi.

Hal pertama yang terjadi adalah bahwa dua file proyek —satu yang berisi instruksi build dan penyebaran universal, dan satu yang berisi pengaturan khusus lingkungan—digabungkan ke dalam satu file proyek. MSBuild kemudian bekerja melalui instruksi dalam file proyek. Ini membangun setiap proyek dalam solusi, menggunakan file proyek untuk setiap proyek. Kemudian memanggil alat lain, seperti Web Deploy (MSDeploy.exe) dan utilitas VSDBCMD untuk menyebarkan konten web dan database Anda ke lingkungan target.

Dari awal hingga akhir, proses build dan penyebaran melakukan tugas-tugas ini:

  1. Ini menghapus konten direktori output, sebagai persiapan untuk build baru.

  2. Ini membangun setiap proyek dalam solusi:

    1. Untuk proyek web—dalam hal ini, aplikasi web MVC ASP.NET dan layanan web WCF—proses build membuat paket penyebaran web untuk setiap proyek.
    2. Untuk proyek database, proses build membuat manifes penyebaran (file.deploymanifest) untuk setiap proyek.
  3. Ini menggunakan utilitas VSDBCMD.exe untuk menyebarkan setiap proyek database dalam solusi, menggunakan berbagai properti dari file proyek—string koneksi target dan nama database—bersama dengan file .deploymanifest.

  4. Ini menggunakan utilitas MSDeploy.exe untuk menyebarkan setiap proyek web dalam solusi, menggunakan berbagai properti dari file proyek untuk mengontrol proses penyebaran.

Anda dapat menggunakan solusi sampel untuk melacak proses ini secara lebih rinci.

Catatan

Untuk panduan tentang cara menyesuaikan file proyek khusus lingkungan untuk lingkungan server Anda sendiri, lihat Mengonfigurasi Properti Penyebaran untuk Lingkungan Target.

Memanggil Proses Build dan Penyebaran

Untuk menyebarkan solusi Contact Manager ke lingkungan pengujian pengembang, pengembang menjalankan file perintah Publish-Dev.cmd . Ini memanggil MSBuild.exe, menentukan Publish.proj sebagai file proyek untuk dijalankan dan Env-Dev.proj sebagai nilai parameter.

msbuild.exe Publish.proj /fl /p:TargetEnvPropsFile=EnvConfig\Env-Dev.proj

Catatan

Sakelar /fl (kependekan dari /fileLogger) mencatat output build ke file bernama msbuild.log di direktori saat ini. Untuk informasi selengkapnya, lihat Referensi Baris Perintah MSBuild.

Pada titik ini, MSBuild mulai berjalan, memuat file Publish.proj , dan mulai memproses instruksi di dalamnya. Instruksi pertama memberi tahu MSBuild untuk mengimpor file proyek yang ditentukan parameter TargetEnvPropsFile .

<Import Project="$(TargetEnvPropsFile)" />

Parameter TargetEnvPropsFile menentukan file Env-Dev.proj , sehingga MSBuild menggabungkan konten file Env-Dev.proj ke dalam file Publish.proj .

Elemen berikutnya yang ditemui MSBuild dalam file proyek gabungan adalah grup properti. Properti diproses dalam urutan kemunculannya dalam file. MSBuild membuat pasangan kunci-nilai untuk setiap properti, asalkan kondisi yang ditentukan terpenuhi. Properti yang ditentukan nanti dalam file akan menimpa properti apa pun dengan nama yang sama yang ditentukan sebelumnya dalam file. Misalnya, pertimbangkan properti OutputRoot .

<OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\</OutputRoot>
<OutputRoot Condition=" '$(BuildingInTeamBuild)'=='true' ">$(OutDir)</OutputRoot>

Ketika MSBuild memproses elemen OutputRoot pertama, menyediakan parameter bernama yang sama belum disediakan, MSBuild menetapkan nilai properti OutputRoot ke .. \Terbitkan\Keluar. Ketika menemukan elemen OutputRoot kedua, jika kondisi mengevaluasi ke true, itu akan menimpa nilai properti OutputRoot dengan nilai parameter OutDir .

Elemen berikutnya yang ditemui MSBuild adalah grup item tunggal, yang berisi item bernama ProjectsToBuild.

<ItemGroup>
   <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
</ItemGroup>

MSBuild memproses instruksi ini dengan membangun daftar item bernama ProjectsToBuild. Dalam hal ini, daftar item berisi satu nilai—jalur dan nama file file file solusi.

Pada titik ini, elemen yang tersisa adalah target. Target diproses secara berbeda dari properti dan item—pada dasarnya, target tidak diproses kecuali ditentukan secara eksplisit oleh pengguna atau dipanggil oleh konstruksi lain dalam file proyek. Ingat bahwa tag Proyek pembuka menyertakan atribut DefaultTargets .

<Project ToolsVersion="4.0" 
         DefaultTargets="FullPublish" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

Ini menginstruksikan MSBuild untuk memanggil target FullPublish , jika target tidak ditentukan saat MSBuild.exe dipanggil. Target FullPublish tidak berisi tugas apa pun; sebaliknya hanya menentukan daftar dependensi.

<PropertyGroup>   
  <FullPublishDependsOn>
     Clean;
     BuildProjects;      
     GatherPackagesForPublishing;
     PublishDbPackages;
     PublishWebPackages;
  </FullPublishDependsOn>
</PropertyGroup>
<Target Name="FullPublish" DependsOnTargets="$(FullPublishDependsOn)" />

Dependensi ini memberi tahu MSBuild bahwa untuk menjalankan target FullPublish , perlu memanggil daftar target ini dalam urutan yang disediakan:

  1. Ini harus memanggil target Bersih .
  2. Ini harus memanggil target BuildProjects .
  3. Ini harus memanggil target GatherPackagesForPublishing .
  4. Ini harus memanggil target PublishDbPackages .
  5. Ini harus memanggil target PublishWebPackages .

Target Bersih

Target Bersih pada dasarnya menghapus direktori output dan semua kontennya, sebagai persiapan untuk build baru.

<Target Name="Clean" Condition=" '$(BuildingInTeamBuild)'!='true' ">
  <Message Text="Cleaning up the output directory [$(OutputRoot)]"/>
  <ItemGroup>
     <_FilesToDelete Include="$(OutputRoot)**\*"/>
  </ItemGroup>
  <Delete Files="@(_FilesToDelete)"/>
  <RemoveDir Directories="$(OutputRoot)"/>
</Target>

Perhatikan bahwa target menyertakan elemen ItemGroup . Saat Anda menentukan properti atau item dalam elemen Target , Anda membuat properti dan item dinamis . Dengan kata lain, properti atau item tidak diproses hingga target dijalankan. Direktori output mungkin tidak ada atau berisi file apa pun sampai proses build dimulai, sehingga Anda tidak dapat membuat daftar _FilesToDelete sebagai item statis; Anda harus menunggu sampai eksekusi berlangsung. Dengan demikian, Anda membuat daftar sebagai item dinamis dalam target.

Catatan

Dalam hal ini, karena target Bersih adalah yang pertama kali dijalankan, tidak ada kebutuhan nyata untuk menggunakan grup item dinamis. Namun, ada baiknya menggunakan properti dan item dinamis dalam jenis skenario ini, karena Anda mungkin ingin menjalankan target dalam urutan yang berbeda pada beberapa titik.
Anda juga harus bertujuan untuk menghindari mendeklarasikan item yang tidak akan pernah digunakan. Jika Anda memiliki item yang hanya akan digunakan oleh target tertentu, pertimbangkan untuk menempatkannya di dalam target untuk menghapus overhead yang tidak perlu pada proses build.

Item dinamis di samping, target Bersihkan cukup mudah dan memanfaatkan tugas Pesan, Hapus, dan RemoveDir bawaan untuk:

  1. Kirim pesan ke pencatat.
  2. Buat daftar file yang akan dihapus.
  3. Hapus file.
  4. Hapus direktori output.

The BuildProjects Target

Target BuildProjects pada dasarnya membangun semua proyek dalam solusi sampel.

<Target Name="BuildProjects" Condition=" '$(BuildingInTeamBuild)'!='true' ">
   <MSBuild Projects="@(ProjectsToBuild)"
            Properties="OutDir=$(OutputRoot);
                        Configuration=$(Configuration);
                        DeployOnBuild=true;
                        DeployTarget=Package"
            Targets="Build" />
  </Target>

Target ini dijelaskan dalam beberapa detail dalam topik sebelumnya, Memahami File Proyek, untuk mengilustrasikan bagaimana tugas dan menargetkan properti referensi dan item. Pada titik ini, Anda terutama tertarik pada tugas MSBuild . Anda dapat menggunakan tugas ini untuk membangun beberapa proyek. Tugas tidak membuat instans baru MSBuild.exe; ini menggunakan instans yang sedang berjalan saat ini untuk membangun setiap proyek. Poin-poin penting yang menarik dalam contoh ini adalah properti penyebaran:

  • Properti DeployOnBuild menginstruksikan MSBuild untuk menjalankan instruksi penyebaran apa pun di pengaturan proyek saat build setiap proyek selesai.
  • Properti DeployTarget mengidentifikasi target yang ingin Anda panggil setelah proyek dibuat. Dalam hal ini, target Paket membangun output proyek ke dalam paket web yang dapat disebarkan.

Catatan

Target Paket memanggil Alur Penerbitan Web (WPP), yang menyediakan integrasi antara MSBuild dan Web Deploy. Jika Anda ingin melihat target bawaan yang disediakan WPP, tinjau file Microsoft.Web.Publishing.targets di folder %PROGRAMFILES(x86)%\MSBuild\Microsoft\VisualStudio\v10.0\Web.

The GatherPackagesForPublishing Target

Jika Anda mempelajari target GatherPackagesForPublishing , Anda akan melihat bahwa itu tidak benar-benar berisi tugas apa pun. Sebaliknya, ini berisi satu grup item yang menentukan tiga item dinamis.

<Target Name="GatherPackagesForPublishing">
   <ItemGroup>
      <PublishPackages 
         Include="$(_ContactManagerDest)ContactManager.Mvc.deploy.cmd">
         <WebPackage>true</WebPackage>
         <!-- More item metadata -->  
      </PublishPackages>
      <PublishPackages 
         Include="$(_ContactManagerSvcDest)ContactManager.Service.deploy.cmd">
         <WebPackage>true</WebPackage>
         <!-- More item metadata -->
      </PublishPackages>
      <DbPublishPackages Include="$(_DbDeployManifestPath)">
         <DbPackage>true</DbPackage>
         <!-- More item metadata -->
      </DbPublishPackages>
   </ItemGroup>
</Target>

Item ini mengacu pada paket penyebaran yang dibuat saat target BuildProjects dijalankan. Anda tidak dapat menentukan item ini secara statis dalam file proyek, karena file yang dirujuk item tidak ada sampai target BuildProjects dijalankan. Sebaliknya, item harus didefinisikan secara dinamis dalam target yang tidak dipanggil sampai setelah target BuildProjects dijalankan.

Item tidak digunakan dalam target ini—target ini hanya membangun item dan metadata yang terkait dengan setiap nilai item. Setelah elemen ini diproses, item PublishPackages akan berisi dua nilai, jalur ke file ContactManager.Mvc.deploy.cmd dan jalur ke file ContactManager.Service.deploy.cmd . Web Deploy membuat file-file ini sebagai bagian dari paket web untuk setiap proyek, dan ini adalah file yang harus Anda panggil di server tujuan untuk menyebarkan paket. Jika Anda membuka salah satu file ini, pada dasarnya Anda akan melihat perintah MSDeploy.exe dengan berbagai nilai parameter khusus build.

Item DbPublishPackages akan berisi satu nilai, jalur ke file ContactManager.Database.deploymanifest .

Catatan

File .deploymanifest dihasilkan saat Anda membangun proyek database, dan menggunakan skema yang sama dengan file proyek MSBuild. Ini berisi semua informasi yang diperlukan untuk menyebarkan database, termasuk lokasi skema database (.dbschema) dan detail pra-penyebaran dan skrip pasca-penyebaran. Untuk informasi selengkapnya, lihat Gambaran Umum Build dan Penyebaran Database.

Anda akan mempelajari selengkapnya tentang bagaimana paket penyebaran dan manifes penyebaran database dibuat dan digunakan dalam Membangun dan Mengemas Proyek Aplikasi Web dan Menyebarkan Proyek Database.

The PublishDbPackages Target

Secara singkat, target PublishDbPackages memanggil utilitas VSDBCMD untuk menyebarkan database ContactManager ke lingkungan target. Mengonfigurasi penyebaran database melibatkan banyak keputusan dan nuansa, dan Anda akan mempelajari selengkapnya tentang hal ini dalam Menyebarkan Proyek Database dan Menyesuaikan Penyebaran Database untuk Beberapa Lingkungan. Dalam topik ini, kita akan fokus pada bagaimana target ini benar-benar berfungsi.

Pertama, perhatikan bahwa tag pembuka menyertakan atribut Output .

<Target Name="PublishDbPackages" Outputs="%(DbPublishPackages.Identity)">

Ini adalah contoh batching target. Dalam file proyek MSBuild, batching adalah teknik untuk melakukan iterasi pada koleksi. Nilai atribut Output,"%(DbPublishPackages.Identity)", mengacu pada properti metadata Identitas dari daftar item DbPublishPackages . Notasi ini, Outputs=%(ItemList.ItemMetadataName), diterjemahkan sebagai:

  • Pisahkan item di DbPublishPackages menjadi batch item yang berisi nilai metadata Identitas yang sama.
  • Jalankan target sekali per batch.

Catatan

Identitas adalah salah satu nilai metadata bawaan yang ditetapkan ke setiap item saat pembuatan. Ini mengacu pada nilai atribut Sertakan dalam elemen Item —dengan kata lain, jalur dan nama file item.

Dalam hal ini, karena tidak boleh ada lebih dari satu item dengan jalur dan nama file yang sama, kami pada dasarnya bekerja dengan ukuran batch satu. Target dijalankan sekali untuk setiap paket database.

Anda dapat melihat notasi serupa di properti _Cmd , yang membangun perintah VSDBCMD dengan sakelar yang sesuai.

<_Cmd>"$(VsdbCmdExe)" 
   /a:Deploy 
   /cs:"%(DbPublishPackages.DatabaseConnectionString)" 
   /p:TargetDatabase=%(DbPublishPackages.TargetDatabase)             
   /manifest:"%(DbPublishPackages.FullPath)" 
   /script:"$(_CmDbScriptPath)" 
   $(_DbDeployOrScript)
</_Cmd>

Dalam hal ini, %(DbPublishPackages.DatabaseConnectionString), %(DbPublishPackages.TargetDatabase), dan %(DbPublishPackages.FullPath) semuanya mengacu pada nilai metadata kumpulan item DbPublishPackages . Properti _Cmd digunakan oleh tugas Exec , yang memanggil perintah .

<Exec Command="$(_Cmd)"/>

Sebagai hasil dari notasi ini, tugas Exec akan membuat batch berdasarkan kombinasi unik dari nilai metadata DatabaseConnectionString, TargetDatabase, dan FullPath , dan tugas akan dijalankan sekali untuk setiap batch. Ini adalah contoh batching tugas. Namun, karena batching tingkat target telah membagi koleksi item kami menjadi batch item tunggal, tugas Exec akan berjalan sekali dan hanya sekali untuk setiap iterasi target. Dengan kata lain, tugas ini memanggil utilitas VSDBCMD sekali untuk setiap paket database dalam solusi.

Catatan

Untuk informasi selengkapnya tentang batching target dan tugas, lihat Batching MSBuild, Metadata Item di Batching Target, dan Metadata Item dalam Batching Tugas.

The PublishWebPackages Target

Pada titik ini, Anda telah memanggil target BuildProjects , yang menghasilkan paket penyebaran web untuk setiap proyek dalam solusi sampel. Menyertai setiap paket adalah file deploy.cmd , yang berisi perintah MSDeploy.exe yang diperlukan untuk menyebarkan paket ke lingkungan target, dan file SetParameters.xml , yang menentukan detail lingkungan target yang diperlukan. Anda juga telah memanggil target GatherPackagesForPublishing , yang menghasilkan koleksi item yang berisi file deploy.cmd yang Anda minati. Pada dasarnya, target PublishWebPackages melakukan fungsi-fungsi ini:

  • Ini memanipulasi file SetParameters.xml untuk setiap paket untuk menyertakan detail yang benar untuk lingkungan target, menggunakan tugas XmlPoke .
  • Ini memanggil file deploy.cmd untuk setiap paket, menggunakan sakelar yang sesuai.

Sama seperti target PublishDbPackages , target PublishWebPackages menggunakan batching target untuk memastikan bahwa target dijalankan sekali untuk setiap paket web.

<Target Name="PublishWebPackages" Outputs="%(PublishPackages.Identity)">

Dalam target, tugas Exec digunakan untuk menjalankan file deploy.cmd untuk setiap paket web.

<PropertyGroup>
   <_Cmd>
      %(PublishPackages.FullPath) 
      $(_WhatifSwitch) 
      /M:$(MSDeployComputerName) 
      %(PublishPackages.AdditionalMSDeployParameters)
   </_Cmd>
</PropertyGroup>
<Exec Command="$(_Cmd)"/>

Untuk informasi selengkapnya tentang mengonfigurasi penyebaran paket web, lihat Membangun dan Mengemas Proyek Aplikasi Web.

Kesimpulan

Topik ini menyediakan panduan tentang bagaimana file proyek terpisah digunakan untuk mengontrol proses build dan penyebaran dari awal hingga akhir untuk solusi sampel Contact Manager. Menggunakan pendekatan ini memungkinkan Anda menjalankan penyebaran skala perusahaan yang kompleks dalam satu langkah berulang, hanya dengan menjalankan file perintah khusus lingkungan.

Bacaan lebih lanjut

Untuk pengenalan yang lebih mendalam tentang file proyek dan WPP, lihat Di dalam Microsoft Build Engine: Menggunakan MSBuild dan Team Foundation Build oleh Sayed Ibrahim Hashimi dan William Bartholomew, ISBN: 978-0-7356-4524-0.