AppVeyor ile .NET NuGet Paketi Oluşturarak Publish Etmek

Merhaba arkadaşlar.

Bu makale konumda biraz farklı bir alana değinerek, sizlere son zamanlarda severek kullandığım bir CI(Continuous Integration) tool’u olan AppVeyor‘un Continuous Deployment fonksiyonunu kullanarak, .NET ile geliştirdiğimiz library’leri nasıl NuGet paketi haline getirip kolay bir şekilde publish edebiliriz konusuna değinmeye çalışacağım.

Daha önce AppVeyor’u kullanmamış arkadaşlar için konuya başlamadan önce belirtmek istiyorum ki, AppVeyor kullanımı open-source projeler için ücretsizdir. Bu makale kapsamında AppVeyor nedir, ne değildir gibi detaylara değinmeyeceğimden dolayı, merak eden arkadaşlar buradan inceleyebilirler.

Bir çoğumuz gerek iş yerlerimizde, gerekse de open source projelerimizde NuGet server üzerinden paketlerimizi bir şekilde yönetiyoruz. CI/CD dünyasının hızla gelişmesi ile birlikte, deployment işlemlerinin automated bir hale getirilmesi sizlerinde bildiği gibi bir çok açıdan bizlere hız ve zaman kazandırmaktadır.

En basitinden şimdi ele alacak olduğumuz NuGet konusuna baktığımızda, eğer herhangi bir CI aracı kullanmıyor isek en basit haliyle:

  • Projeyi build et
  • Varsa test case’lerini çalıştır
  • NuGet Package Explorer’ı kullanarak bir NuGet paketi oluştur
  • Paketleme sonucunda elde edilen “*.nupkg” dosyasını local NuGet üzerine veya nuget.org’a girerek, upload et.

gibi manuel süreçler gerçekleştiriyoruz.

AppVeyor ise bu adımları bizim için automated bir hale getiriyor. Projeyi commit ettikten sonra gerçekleşen adımlar ise:

  • NuGet paketlerini restore ediyor
  • Projeyi istediğiniz modda build ediyor
  • Varsa test case’lerini çalıştırıyor
  • Başarılı bir şekilde adımlar gerçekleşiyor ise, tanımlamış olduğumuz NuGet spec’lerine göre bir “*.nupkg” artifact’i oluşturuyor
  • Oluşan artifact’i NuGet üzerine publish ediyor

ve bu süreçlerin hepsi otomatik olarak işliyor. Ne kadar güzel değil mi? 🙂

İşin aslına baktığımızda her ne kadar çok da fazla DevOps konuları ile içli dışlı olmasam da, hayatlarımızı ne kadar da kolaylaştırdıkları bir gerçek!

Dilerseniz şimdi örneğimize geçelim. Bunun için öncelikle GitHub üzerinde “ci-nuget-sample” isminde public bir repository oluşturuyorum. Oluşturmuş olduğumuz repository’i, aşağıdaki gibi Visual Studio üzerinden clone edelim.

Clone işlemini tamamladıktan sonra içerisine “HelloService” isminde yeni bir class library oluşturalım ve ardından içerisine “HelloService” isminde bir class tanımlayalım. Bu class’ın görevi, çağırıldığında “Hello!” demek olsun. 🙂

“HelloService” class’ını aşağıdaki gibi kodlayalım.

namespace HelloService
{
    public class HelloService
    {
        public string SayHello()
        {
            return "Hello!";
        }
    }
}

Şimdi istiyoruz ki biz bu “HelloService” i, NuGet üzerinden bir paket olarak sunalım.

NuGet Specification Oluşturma

Öncelikle bir NuGet paketi oluşturabilmemiz için NuGet spec file’ını tanımlamamız gerekmektedir. Bunun için “HelloService” library’si üzerine sağ tıklayıp “Add > New Item” penceresine geldikten sonra, “HelloService.nuspec” adında bir file oluşturalım.

Oluşturmuş olduğumuz nuspec file’ını ise aşağıdaki gibi tanımlayacağız. Ben tanımlama sırasında en yaygın kullanılan metadata element’lerini kullanmaya çalışacağım. Tanımlama sırasında sizlerde burayı referans alabilirsiniz.



  
    HelloService
    $version$
    HelloService
    Gökhan Gökalp
    Gökhan Gökalp
    https://github.com/GokGokalp/ci-nuget-sample
    false
    Say hello!
    Copyright 2017 Gökhan Gökalp
    Hello Service
  
    
    
  

Burada bulunan “id”, “version”, “description” ve “authors” alanları doldurulması gereken must alanlardır. Bunların dışında kalanlar ise opsiyonel olarak eklenebilmektedir. Burada dikkat ederseniz “version” kısmına value olarak “$version$” parametresini ekledim. Versiyonlama işlemini ilgili paketim için manuel olarak yönetmek yerine, AppVeyor’un bu işlemi otomatik olarak gerçekleştirebilmesini sağlamış oluyoruz. (Bu işlemin AppVeyor üzerinden nasıl handle edildiğini ilerleyen kısımda göreceğiz)

Spec üzerindeki “metadata” dışında “files” kısmına baktığımızda ise, oluşturulacak olan NuGet paketinin içerisinde hangi assembly’lerin olacağını, nelerin exclude edileceğini tanımlayabiliyoruz.

Bunlara ek olarak da eğer paketimiz herhangi bir dependency’e ihtiyacı var ise, yine aşağıdaki gibi tanımlayabilmek mümkündür:

  
    
  

NuGet specification file’ı artık hazır durumdadır.

AppVeyor ile GitHub Entegrasyonu

Bu kısımda ise GitHub üzerinde oluşturmuş olduğumuz “ci-nuget-sample” repository’sini, AppVeyor ile entegre çalışır hale getireceğiz. Yani repository üzerine herhangi bir commit geldiğinde, otomatik olarak AppVeyor’un tetiklenmesini sağlayacağız.

Bunun öncesinde, öncelikle buraya tıklayarak bir AppVeyor hesabı oluşturalım. Hesabı oluştururken “Plan” sekmesinden “FREE – for open-source projects” seçeneğini seçebilirsiniz veya GitHub hesabınız var ise GitHub seçeneğini tıklayarak da GitHub hesabınız ile giriş yapabilirsiniz. AppVeyor’a giriş yaptıktan sonra “Projects” sekmesinden “New Project” e tıklayarak, ben GitHub hesabım ile oturum açtığım için otomatik olarak GitHub repository’lerimi aşağıdaki gibi getirdi.

Bu ekran üzerinden örneğimiz için oluşturmuş olduğumuz “ci-nuget-sample” projesinin, sağ tarafında bulunan “ADD” seçeneğine basalım.

Ekleme işlemi başarılı bir şekilde gerçekleştikten sonra, aşağıdaki gibi bir ekranı karşımıza getirecektir.

Gerçekleştirdiğimiz bu işlem ile AppVeyor, GitHub üzerindeki “ci-nuget-sample” projemizin webhook kısmına kendisini default olarak eklemektedir. Emin olmak için ise GitHub üzerindeki repository’nin “Settings” sekmesinden, “Webhooks” kısmına girelim.

Yukarıda gördüğümüz gibi “https://ci.appveyor.com/api/github/webhook” url’i ile kendisini eklemiş bulunmaktadır.

Trigger ayarlarını değiştirebilmek için ise, “Edit” butonuna basalım.

Yukarıda bulunan “Payload URL” kısmında AppVeyor’un projeniz için vermiş olduğu URL yer almaktadır. Eğer AppVeyor otomatik olarak webhook ayarını yapmamış olsaydı, GitHub repository setting’i üzerinden yine “WebHooks” sekmesinden “New WekHook” diyerek, “Payload URL” i girmemiz ve trigger ayarını seçmemiz yeterli olacaktı. Biraz aşağıya baktığımızda bulunan “Let me select individual events.” ayarlarından ise, hangi event’lar doğrultusunda AppVeyor’un trigger olmasını istediğimizi seçebilmekteyiz. Burada AppVeyor tarafından default olarak “Pull request” ve “Push” event’leri seçili olarak gelmektedir.

“Pull request” event’ının güzel tarafı ise herhangi bir brach’e bir pull request geldiğinde, merge işlemini gerçekleştirmeden hemen önce AppVeyor tarafından otomatik olarak build ediliyor ve merge işlemini gerçekleştirirseniz ne ile karşılaşabileceğinizi görebiliyorsunuz.

Biz örneğimiz gereği sadece master branc’i üzerinden ilerleyeceğiz. GitHub üzerindeki ayarlarımız tamamlandığına göre, henüz kodumuzu commit etmeden birde AppVeyor üzerindeki ayarlara bir göz atalım. Bunun için AppVeyor üzerindeki “SETTINGS” sekmesine gelelim.

İlk olarak “Next build number” kısmından bir sonraki build’in hangi numaraya sahip olacağını ayarlayabiliyorsunuz ve bu build number, versiyon numarası olarak da kullanılabilmekte. Hatırlarsanız NuGet spec tanımlarken version sekmesine “$version$” olarak bir parametre vermiştik. İşte bu parametreyi AppVeyor deployment aşamasında, “Build version format” kısmında belirtmiş olduğunuz format’a göre bir versiyon numarası set etmektedir. Bunun dışında diğer bir önemli kısım ise “Branches to build” kısmıdır. Biz burada build işlemi sonrası otomatik olarak NuGet paketi oluşturup publish edeceğimiz için, “All branches” seçeneği yerine “Only branches specified below” kısmını seçerek buraya master branch’i belirtmek gerekiyor. Şuanda örneğimiz gereği tek bir branch’e sahip olduğumuz için, pek bir önemi bulunmamaktadır.

Aşağı kısımdaki seçeneklere baktığımızda ise burada belki kullanabileceğiniz “Ignore appveyor.yml” seçeneği olabilir. AppVeyor üzerinde build ve deployment tarzı işlemlerinizi, “yml” formatında bir file hazırlayarak da gerçekleştirebilirsiniz. Eğer bu tarz işlemlerin dışarıdan erişilmesini istemiyorsanız, ignore seçeneğini seçerek sadece arayüz üzerindeki ayarlar ile gerçekleşebilmesini sağlayabilirsiniz.

Bunların dışında diğer script alanları ile ilgili şuan için bir ihtiyacımız yok.

Şimdi geldi artık build kısımlarını ayarlamaya. Hemen sol sekmeden “Build” kısmına geçelim.

Burada üst seçeneklerden “MSBUILD” seçili olduğundan emin olalım. Bunun ardından “Configuration” kısmından build işlemi gerçekleşirken “Debug” mı yoksa “Release” konfigürasyonunun mu kullanılacağını belirteceğiz. Yukarıda gördüğümüz gibi buraya “Release” yazalım.

Sayfanın alt kısımındaki ayarlara baktığımızda ise burada “Before build script” kısmını “CMD” seçelim ve buraya aşağıdaki gibi “nuget restore” command’ını yazalım. Bu command sayesinde proje build olurken, kullandığımız herhangi bir NuGet paketleri varsa otomatik olarak restore olacaktır.

“After build script” kısmında ise, “PS” kısmını seçelim ve buraya yukarıda olduğu gibi aşağıdaki PowerShell Script’ini yazalım.

nuget pack HelloService\HelloService.nuspec -version $env:APPVEYOR_BUILD_VERSION
Get-ChildItem .\*.nupkg | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }

Bu script ile kısaca nuspec file’ın path’ini belirterek, versiyon numarasını environment üzerinden “APPVEYOR_BUILD_VERSION” parametresi ile almasını ve ardından bir “*.nupkg” file’ı oluşturup onu push etmesini söylüyoruz.

Şimdi geriye sadece deployment ayarları kaldı. Sol menüden hızlıca “Deployment” sekmesine geçelim ve aşağıdaki gibi NuGet ayarlarını yapmaya başlayalım.

İlk olarak açılan ekranın providers bölümünden, “Add deployment” a tıklayarak NuGet provider’ını seçelim.

Bu kısımda biz direkt olarak nuget.org üzerine publish edeceğimiz için, bu kısmı boş bırakıyoruz. Burada yapmamız gereken ilk şey kendimize bir NuGet hesabı oluşturup, “API key” bilgisini buraya girmektir. NuGet üyeliğini ise buradan gerçekleştirebilirsiniz. Üyelik işlemini tamamladıktan sonra, “Accounts” sayfası altında bulunan “Credentials” sekmesinden “API Keys” bilgisine ulaşabilirsiniz.

API key’ini aldıktan sonra AppVeyor üzerindeki “API key” bölümüne girelim ve ardından, “Do not publish symbol packages” seçeneğini seçelim. Daha sonra “Deploy from branch” seçeneğini seçerek açılan alana ilgili branch adını yazalım ve artık ayarları kaydedelim.

Bu adımların ardından deployment kısmının son hali ise aşağıdaki gibi olacaktır.

GitHub’a commit işlemi için Visual Studio’ya artık geri dönebiliriz. Eğer herhangi eksik bir şey yapmadı ise, HelloService’i commit ettiğimiz an NuGet üzerinde bir paket haline gelecektir. 🙂

Commit işleminin ardından AppVeyor üzerinden “LATEST BUILD” sekmesine gelelim ve ilgili commit’in buraya gelip build işlemi için queue’ya alındığını görebiliriz.

Build işlemi burada kısa bir süre içerisinde başlayacaktır ve başladığında ise aşağıdaki gibi bir ekranla karşılaşacağız.

Burada dikkat edersek AppVeyor’da ilk build numaramız “1” olduğu için, ayarlamış olduğumuz version format’ı doğrultusunda ilk versiyonu “1.0.1” olarak belirlemiştir. AppVeyor, GitHub üzerinden belirtmiş olduğumuz master branch’ini çekerek, build işlemi sırasında “nuget restore” işlemini de gerçekleştirmiştir. Sonrasında ise tanımlamış olduğumuz nuspec file’ını kullanarak, “HelloService.1.0.1.nupkg” paketini oluşturmuştur ve NuGet’e publish işlemini başarıyla gerçekleştirmiştir.

Şimdi NuGet hesabımız üzerinden “Manage My Packages” kısmına girerek, buradan HelloService paketini seçelim ve detaylarına bir bakalım.

Evet! Paketimiz “HelloService” ismi ile ve “1.0.1” versiyon numarası ile başarılı bir şekilde NuGet üzerinde yerini almış bulunmaktadır.

Her ne kadar farklı bir alana değinmiş olsam da, eminim sizlerinde bir çok konuda işine yarayacaktır. Konuyu burada sonlandırmadan önce son bir şey daha eklemek istiyorum. GitHub’da bulunan bazı projeler üzerinde sizlerde görmüşsünüzdür “build passing” veya “nuget package 1.0.0” gibi versiyon numaralarının görsellerini. Kendi paketim üzerinden örnek vermek gerekirse:

Burada AppVeyor logosu ile gördüğümüz “build passing” ve nuget package versiyonları gibi görselleri ekleyebilmek için, AppVeyor’da “Settings” sekmesinin altında bulunan “Badges” kısmına girelim.

Burada görebildiğiniz gibi kullanmak istediğiniz görsel URL’lerini AppVeyor sizlere sunmaktadır. Readme içerisinde kullanabilmek için ise, “Sample markdown code” ile başlayan kısımdaki kodu kullanarak sizlerde readme’leriniz üzerine ekleyebilirsiniz.

Makale boyunca gerçekleştirdiğimiz örnek uygulamaya ve “appveyor.yml” dosyasına aşağıdaki link üzerinden erişebilirsiniz.

Takipte kalın.

https://github.com/GokGokalp/ci-nuget-sample

Gökhan Gökalp

Recent Posts

Securing the Supply Chain of Containerized Applications to Reduce Security Risks (Policy Enforcement-Automated Governance with OPA Gatekeeper and Ratify) – Part 2

{:tr} Makalenin ilk bölümünde, Software Supply Chain güvenliğinin öneminden ve containerized uygulamaların güvenlik risklerini azaltabilmek…

6 months ago

Securing the Supply Chain of Containerized Applications to Reduce Security Risks (Security Scanning, SBOMs, Signing&Verifying Artifacts) – Part 1

{:tr}Bildiğimiz gibi modern yazılım geliştirme ortamında containerization'ın benimsenmesi, uygulamaların oluşturulma ve dağıtılma şekillerini oldukça değiştirdi.…

8 months ago

Delegating Identity & Access Management to Azure AD B2C and Integrating with .NET

{:tr}Bildiğimiz gibi bir ürün geliştirirken olabildiğince farklı cloud çözümlerinden faydalanmak, harcanacak zaman ve karmaşıklığın yanı…

1 year ago

How to Order Events in Microservices by Using Azure Service Bus (FIFO Consumers)

{:tr}Bazen bazı senaryolar vardır karmaşıklığını veya eksi yanlarını bildiğimiz halde implemente etmekten kaçamadığımız veya implemente…

2 years ago

Providing Atomicity for Eventual Consistency with Outbox Pattern in .NET Microservices

{:tr}Bildiğimiz gibi microservice architecture'ına adapte olmanın bir çok artı noktası olduğu gibi, maalesef getirdiği bazı…

2 years ago

Building Microservices by Using Dapr and .NET with Minimum Effort – 02 (Azure Container Apps)

{:tr}Bir önceki makale serisinde Dapr projesinden ve faydalarından bahsedip, local ortamda self-hosted mode olarak .NET…

2 years ago