středa 21. prosince 2011

Vlastní úlohy pro MSBuild

Automatizujte. Váš čas je drahý. Nedělejte ručně činnosti, které za Vás mohou udělat stroje během několika okamžiků a s minimální chybovostí.

Součástí Visual Studia je buildovací systém MSBuild. MSBuild pracuje ve Visual Studiu na pozadí při kompilaci projektů do spustitelného kódu. MSBuild je také využíván při týmovém vývoji na speciálních buildovacích serverech. Ať už provádíte build produkční verze aplikace, build testovací verze, build kontinuální integrace nebo úplně jinou automatizovanou úlohu, může se stát, že vyvstane specifická potřeba, kterou standardní úlohy MSBuildu nezvládnou. Pak se přiblíží okamžik, kdy budete potřebovat napsat úlohu vlastní. Určitě se toho nebojte. Odměnou Vám bude zrychlení práce a uznání ostatních členů vývojového týmu ;-)

Vytvoření knihovny s úlohou

Vytvoříme projekt typu Class Library. V našem příkladu založíme projekt Firma.Nastroje.Build.Ulohy.

Do projektu přidáme reference na frameworkové assembly Microsoft.Build.Framework a Microsoft.Build.Utilities.v4.0 (pro .NET FW 4.0).

Založíme třídu úlohy. Třída musí implementovat rozhraní Microsoft.Build.Utilities.ITask. Je vhodné podědit abstraktní třídu Microsoft.Build.Utilities.Task. Překryjeme metodu Execute(), která je vyvolána MSBuildem během provádění. Provádění úlohy je konfigurovatelné přes nastavení veřejných vlastností třídy. Nezapomeňte projekt zkompilovat ;-)

using System;
 
namespace Firma.Nastroje.Build.Ulohy
{
    /// <summary>
    /// Implementace mojí úlohy sestavení.
    /// </summary>
    public class MojeUloha : Microsoft.Build.Utilities.Task
    {
        /// <summary>
        /// Povinný parametr úlohy.
        /// </summary>
        [Microsoft.Build.Framework.Required]
        public string PovinnyParametrUlohy { getset; }
 
        /// <summary>
        /// Nepovinný parametr úlohy.
        /// </summary>
        public string NepovinnyParametrUlohy { getset; }
 
        /// <summary>
        /// Provádění úlohy.
        /// </summary>
        /// <returns>true, pokud je provádění úspěšné.</returns>
        public override bool Execute()
        {
            throw new NotImplementedException();
        }
    }
}

Nasazení knihovny na buildovací počítač

Všechny rozšiřující knihovny, které by měl znát MSBuild, umístěte na buildovacím počítači do adresáře definovaného v proměnné $(MSBuildExtensionsPath). Obvykle se jedná o "c:\Program Files (x86)\MSBuild". Doporučuji knihovnu zařadit ještě do podadresáře podle firmy nebo projektu. Ukázková knihovna bude mít v našem příkladě absolutní cestu "c:\Program Files (x86)\MSBuild\Firma\Firma.Nastroje.Build.Ulohy.dll".

Použití v buildovacím projektu

Nejprve musíme zadeklarovat naši úlohu na začátku řídícího projektového souboru (.proj, .csproj) ...

<UsingTask 
   TaskName="MojeUloha" 
   AssemblyFile="$(MSBuildExtensionsPath)\Firma\Firma.Nastroje.Build.Ulohy.dll"/>

... a poté zadefinovat konkrétní použití buildovací úlohy:

<MojeUloha
   PovinnyParametr="HodnotaPovinnehoParametru"
   NepovinnyParametr="HodnotaNepovinnehoParametru"
   />

Poznámky

  • Pro účely ladění třídy Vaší úlohy si vytvořte jednotkové testy, viz. TDD.
  • Framework Vaší knihovny musí být na buildovacím počítači podporován. Úlohy v jednom buildovacím projektu mohou být napsány pro různé frameworky.
  • Úlohy mohou poskytovat i návratové argumenty.
  • Argumenty úloh mohou být kolekce hodnot, např. kolekce názvů souborů.
  • Alternativou k vlastním úlohám pro MSBuild je vytvoření spustitelné exe aplikace, které předáte potřebné parametry přes příkazovou řádku.

3 komentáře:

  1. Protože zastávám ideu, že úplně všechno by mělo být v repozitáři, musím vyjádřit svoji nelibost nad kopírováním vlastního Tasku kamsi do Program Files ;-)

    Ale konkrétní otázka - jaký takový typický Task používáš? Nikdy jsem neměl potřebu ho použít...

    OdpovědětSmazat
  2. Augi, to byl teda fofr ;-)

    S tím repozitářem souhlasím. Zdrojáky úlohy v repozitáři jsou určitě a je fakt, že by tam mohla být i výsledná binární knihovna.

    Když pomocí TFS buildu připravujeme distribuci produkční verze aplikace, její součástí jsou všechny databázové změnové skripty. Zákazníci mají obecně různé verze (stav) naší databáze. Proto je nutné v rámci nasazení aplikace provést kontrolu, které skripty je nutné spustit. Moje úloha projde distribuční adresář a vytvoří pomocný skript pro kontrolu "nespuštěných" skriptů. Taková pomůcka pro nasazení. Nevím, jestli jsem to napsal srozumitelně ;-) Není to sice úplně sofistikovaný způsob aktualizace verze, ale je to bohužel důsledek heterogenního vývojového prostředí v naší firmě :(

    Další úlohou může být generování přehledu změn v nových verzích. Zdrojem jsou naše interní pracovní položky (work items) na TFS, které mohou, ale nemusí, obsahovat informaci, kterou uvidí uživatelé v přehledu změn v nové verzi.

    OdpovědětSmazat
  3. Ahaa - takže ty Tasky nepoužíváš ani tak pro vlastní kompilaci, ale spíš až pro postkompilační věci, které děláš na integračním/build serveru, na kterém běží TFS (které ty Tasky podporuje). To dává smysl.

    OdpovědětSmazat