domingo, 20 de março de 2022

Build via Microsoft Hosted Agent e Azure Pipelines

Neste post fugirei um pouco da parte de desenvolvimento e focarei em DevOps. Hoje falarei de forma pouco conhecida de build, mas que viabiliza (em ambientes saudáveis) zerar o custo de build com máquinas virtuais alocadas especificamente para este fim. Além da possibilidade de custo zero, outra grande vantagem deste tipo de build é a possibilidade de rodar N pipelines no Azure ao mesmo tempo (sem ter que criar N servers do tipo PaaS para isso) mas para isso você precisaria pagar para ter mais Azure Agents ou Scale Sets, ou seja, sair do custo 0, custo este que não chega nem perto do custo de storage do server convencional rs.

Assumo que estou com pouco tempo para escrever aqui, então não entrarei em muitos detalhes do processo, somente lhes darei o caminho das pedras para que vocês consigam evoluir sozinhos. Como referência utilizem este link oficial da Microsoft: Build automation that uses Microsoft-hosted agents and Azure Pipelines - Finance & Operations | Dynamics 365 | Microsoft Docs 

Este tipo de build precisa de uma Solution do Visual Studio, com projetos vazios que referenciem cada model existente na branch que sofrerá o build. Caso você tenha herdado um ambiente com models a dar com Pau, a dica é que crie um console application no visual studio que varra todos os descriptors e crie os .rnrprojs dentro da solution, É simples, porém um pouco trabalhoso, caso precise posso enviar a que fiz junto com o Alberto Suzuki (Alberto Suzuki | LinkedIn), só chamar via inbox, não é algo que eu me orgulhe para postar aqui. Esta solution deve sofrer checkin na branch que sofrerá o build, para que possa ser referenciada no Pipeline

Grosseiramente falando, este tipo de build baixará os arquivos do Core Microsoft, e os utilizará para realizar o build do código personalizado do cliente. Isso tudo com um server genérico que contenha uma versão mais recente do Visual Studio. Ao contrário do que muitos imaginam, o build do D365 F&O via Azure Pipeline, seja através do servidor convencional ou do Azure Agent, somente compila objetos de personalização portanto o tempo de compilação e empacotamento NÃO deve demorar muito (vejo ambientes compilando e empacotando em 10, 15 minutos, mas é lógico que depende do DynaCus implementado rsrs). Evitem criar muitas models, isso afeta o tempo de compilação, em um outro post posso detalhar melhor o por que, no entanto até lá, a dica que posso dar é que utilizem o log do DevOps para entender por que isso acontece.

Bom, então onde podemos localizar e disponibilizar estes arquivos para que o Pipeline consiga baixar e utilizar na compilação? Para isso você precisa acessar o nosso sistema de ciclo de vida do produto, mais conhecido como LCS. Navegue até a pasta de Shared Asset Library, aba Nuget Packages e baixe os arquivos correspondentes à versão do ambiente que quiser compilar, faça isso dentro de um servidor do Azure pois é necessária uma boa velocidade de upload que muito provavelmente sua internet local não terá:


Atualmente são 4 arquivos necessários. Utilize sempre os mais recentes. Pelo que percebi o minor version utilizado sempre será o do Platform Update. Não são liberados arquivos com quality services, a não ser que gerem um HOTFIX, como no caso da imagem.

Uma vez baixados os arquivos (como dito anteriormente, em um server no azure) é o momento de realizar o upload destes arquivos (é aqui que a sua internet local não vai aguentar o tranco) na sessão de Artifacts de seu projeto no DevOps. Para isto, faça o seguinte:

1 - Acesse a sessão de Artifacts do seu projeto no Azure DevOps, e selecione o botão Connect to Feed, aparecerão N opções de conexão, selecione a Nuget.exe. Baixe o executável do Nuget.exe através do botão Get the Tools. Copie TODO o XML da sessão Project Setup e coloque em um arquivo chamado nuget.config:





2 - Crie uma pasta e coloque os Nuget Packages que você baixou, o arquivo nuget.config criado a partir do passo acima e também coloque o nuget.exe . Tudo em uma pasta só!

3 - Vá no DevOps e gere uma Personal Key, esta deverá ser utilizada quando for solicitado o password no passo seguinte, via CMD. Lembrando que vc precisa ter permissões suficientes para subir arquivos no Artifacts, entre em contato com a sua EUquipe, to brincando, com o setor de infra para liberar os acessos necessários, na dúvida vá de admin que não tem erro!



4 - Abra o CMD, execute um CD para a pasta que você criou com todos os arquivos e rode os seguintes comandos. Durante a execução será pedido o seu endereço de email e sua senha, que é o Personal Access Token gerado no passo supracitado. O primeiro parâmetro é o nome do Feed, geralmente é o nome da Org do Azure DevOps e o segundo parâmetro é o nome do arquivo, não precisa do caminho completo pois como você executou o CD o CMD já buscará naquele diretório:

nuget.exe push -Source "NomeDoFeed" -ApiKey az microsoft.dynamics.ax.application.devalm.buildxpp.10.0.1084.80.nupkg
nuget.exe push -Source "NomeDoFeed" -ApiKey az microsoft.dynamics.ax.platform.compilerpackage.7.0.6253.76.nupkg
nuget.exe push -Source "NomeDoFeed" -ApiKey az microsoft.dynamics.ax.applicationsuite.devalm.buildxpp.10.0.1084.80.nupkg
nuget.exe push -Source "NomeDoFeed" -ApiKey az microsoft.dynamics.ax.platform.devalm.buildxpp.7.0.6253.76.nupkg

Uma vez feito o upload de todos os arquivos com sucesso, você terá um feed parecido com isso no seu DevOps:


Com os arquivos disponíveis no Azure Devops, agora é o momento de viabilizar fazer a referencia destes arquivos com a execução do seu pipeline, para isso suba na raiz de sua branch aquele arquivo nuget.config, também crie mais um arquivo chamado packages.config faça a referencia com o nome e versão dos arquivos que sofreram upload e por final suba-o também na raiz da branch que sofrerá o build. O packages.config deve respeitar o formato abaixo:

<?xml version="1.0" encoding="utf-8"?>
<packages>
    <package id="Microsoft.Dynamics.AX.Platform.DevALM.BuildXpp" version="7.0.5968.16973" targetFramework="net40" />
    <package id="Microsoft.Dynamics.AX.Application.DevALM.BuildXpp" version="10.0.793.16" targetFramework="net40" />
    <package id="Microsoft.Dynamics.AX.ApplicationSuite.DevALM.BuildXpp" version="10.0.793.16" targetFramework="net40" />
    <package id="Microsoft.Dynamics.AX.Platform.CompilerPackage" version="7.0.5968.16973" targetFramework="net40" />
</packages>


Agora crie um Pipeline utilizando o seguinte template: Dynamics365-Xpp-Samples-Tools/xpp-ci.yml at master · microsoft/Dynamics365-Xpp-Samples-Tools · GitHub

Com o pipeline criado, na aba Pipeline selecione o seguinte, é ai que você referencia o Microsoft Hosted Agent e deixa de utilizar um server convencional para utilizar um serviço gratuito (até uma hora de execução do Pipeline, depois desse tempo a conexão cai) da Microsoft:



 Deixe o Get Sources da forma abaixo:


Desabilite o passo "Add Licenses to Deployable Package" (na maioria das vezes você não utilizará isso, a não ser que você seja um ISV) 


Referencie a Solution com os Projects de CADA model existente:



Com isso, você já poderá executar o seu Pipeline (e enfrentar algum errinho ou outro rsrs). O resultado deve ser algo parecido com isso aqui:


O print acima é de um ambiente controlado, perceba que o build demorou somente 6 minutos. No entanto, caso o caos esteja implantando no seu cliente e a execução do seu Pipeline demore mais do que uma hora, considere a compra de mais horas de Microsoft Hosted Agent ou a criação de um Scale Set. Caso dinheiro não seja um problema, vá de Scale Set, por ele você pode criar uma máquina bem potente, a ponto de diminuir seu tempo de compilação e empacotamento.

O grande pulo do gato, é que você utiliza um genuíno SaaS neste tipo de build. Isso torna seu build mais escalável, confiável e te da mais flexibilidade no gerenciamento de execução dos Pipelines que estiverem sob sua jurisdição.

Bom, é basicamente isso. Espero que este post tenha ao menos dado uma luz do que é essa forma de build, que pelo que percebo ainda é pouco conhecida aqui pelo BR.

No próximo post te ensino como implantar de forma automática o pacote gerado pelo Pipeline, em sua Sandbox!