Na obsah stránky

Jeden balíček na všechno

Aleš Roubíček | | # permalink

„Jak to vypadá s tím balíčkem pro Honzu?“ „V pohodě, v podstatě je připravenej, jen tam přidám, aby se generovala rovnou i databáze a nainstalovala windows service…“ Tak určitě. Já vůl. Prej jen…

Nakonec to bylo o dost těžší než jsem čekal. Scénář, který jsem si představoval, zdál se být chvíli i nemožný. Ale vždyť to musí jít! Wizard to dokáže, tak proč bych to neměl dokázat já? Zakopanej pes byl nakonec v neštědře zdokumentované featůře.

Již pár let používám k deployování webových aplikací MsDeploy (aka Web Deployment Tools). Většinou je peklo jen s tím, nastavit cílový server, aby vše běhalo jak má. Tedy hlavně nastavení nejrůznějších práv. To už se naštěstí za tu dobu změnilo a stačí jen spustit pár PowerShellových scriptů. Mám automatizovaný deploy jak webu, databáze, tak i instalaci windows služeb. Jinak mi to ani moje závislost na Continuous Delivery nedovolí.

Jenže jedna věc je mít sadu scriptů pro stroj a druhá věc je mít instalační balíček, který je bez problémů schopný nasadit člověk. Ano, mohl by dostat sadu scriptů a hromadu souborů, se kterýma ty scripty pracují, ale potenciální možnost zanesení chyby je vysoká. A komfort velmi nízký.

První pokus

Nejprve jsem se snažil nasynchronizovat jednotlivé kroky do cílového balíčku. Nejprve jsem přes MsBuild /t:Package vytvořil balíček s webem. Databázové schema verzujeme pomocí databázového projektu ve Visual Studiu a tak pro deploy používám již zastaralý dbSqlPackage provider. Tak jsem se ho snažil syncnout do balíčku. Povedlo se, ale manifest v balíčku obsahoval, jen deploy databáze. Uáááá. Už jsem pomalu propadal beznaději a přemýšlel o tom, jak napíšu uživatelsky přívětivý script. To aby UX nepřišlo na úbytě.

Popravdě, koho z vás by napadlo, že tohleto může vést k cíli? Mně to trvalo asi hodinu. A docvaklo mi to až díky tomuhle nešťastníkovi.

Jak na to?

Základem je nevytvářet balíček rovnou, ale vytvořit si nejprve manifest, který obsahuje jednotlivé kroky deploymentu. Ten můj vypadá nějak tak:

<sitemanifest>
  <dbDacFx path='$dbSource' />
  <runCommand path='$presync' waitInterval='30000'/>
  <dirPath path='$winSource' />
  <runCommand path='$postsync' waitInterval='30000'/>
  <IisApp path='$webSource' managedRuntimeVersion='v4.0'/>
  <setAcl path='$webSource' setAclResourceType='Directory'/>
  <setAcl path='$webSource' setAclResourceType='Directory' setAclUser='anonymousAuthenticationUser'/>
</sitemanifest>

Můžete si povšimnout, že je parametrizovaný. To proto, že ho generuju v build scriptu pro konkrétní implementační projekt.

$dbSource je cesta k dacpac souboru, který je výstupem databázového projektu.
$winSource je cesta k bin adresáři windows služby.
$webSource je cesta k PackageTmp adresáři, kde je připravená webová aplikace.

A konečně $presync a $postsync jsou cesty k vygenerovaným cmd souborům, které se spustí na cílovém stroji. PreSync zastaví a odinstaluje již běžící službu:

net stop Svc_$instance
$installUtil /u /name=Svc_$instance $destPath\$instance\Svc.exe

PostSync nainstaluje novou verzi a tu následně spustí:

$installUtil /name=Svc_$instance $destPath\$instance\Svc.exe
net start Svc_$instance

Opět jsou generované scriptem pro konkrétní instance.

Tím mám připravený manifest a všechno, co potřebuju pro úspěšné vytvoření balíčku. Nyní už jen stačí balíček vygenerovat:

$source = "manifest=$manifest"
$dest = "package=$pkgLocation"

exec { msdeploy -verb:sync -source:$source -dest:$dest }

Kde $manifest je cesta k vygenerovanému manifestu a $pkgLocation je cesta, kde najdu vygenerovaný balíček. No a to je celá magie. Ani to moc nebolelo, když už se ví jak na to. :)

Teď už jen zbývá umožnit Honzovi vyplnit konfigurační údaje pro konkrétní servery…

Našli jste v článku chybu? Máte námět na reportáž? Založte mi ticket.