quarta-feira, 31 de agosto de 2022

Como recuperar mais detalhes sobre um erro, através do Environment monitoring

Por vezes a tratativa de exceção do desenvolvedor não nos dá ideia do que ocorreu em determinado processamento em que houve falha, diante desta possibilidade precisamos recorrer a uma ferramenta que está disponível em ambientes UAT e de Produção que é o Enviroment Monitoring. 

Para acessar o Enviroment Monitoring, acesse a página de seu ambiente via LCS e desça até o final. Haverá um hyperlink como na imagem abaixo:


Selecione o hyperlink citado acima e aparecerá uma tela com uma aba chamada Activity, selecione-a altere os parâmetros como falarei a seguir.

É muito importante que seu filtro busque informações no momento exato que determinada exception ocorreu. Caso você não tenha essa informação, peça para que um usuário execute o processo mais uma vez e lhe passe a hora exata em que isso foi feito. Com o horário em mãos, atribua um range nos campos Start date (UTC) e End date (UTC) de forma a garantir que aquele momento em que a exception ocorreu esteja incluso neste período. Caso apareça o erro em um dialog, peça para o usuário lhe passar o activity id que aparecer, ele te ajuda a garimpar as informações quando tiver o excel do log raw em mãos.

Estamos aqui tentando achar uma agulha no palheiro, então é importante também alterar para que o Row Limit seja o máximo suportado, de 5000. Para que esse campo apareça selecione o botão "Show Options".



Você também pode selecionar mais colunas do que as que vem por padrão, selecionando o botão "Show Column Options":




Atribuidos os filtros e parâmetros, selecione o botão "Search" e em seguida o "Export Grid". O "Export Grid" vai lhe gerar um excel com as mesmas infos que aparecem no relatório do LCS. Eu prefiro utilizar o excel para buscar as informações.

A partir dai, utilize a imaginação para filtrar as informações da planilha de modo a encontrar o que você precisa. Você pode utilizar o activity id citado anteriormente, ou qualquer outra coluna para realizar a busca. 

O que eu faço geralmente e que funciona pra mim é ir até à coluna infoMessage, aplicar um filtro nela e navegar pelas informações agrupadas que o filtro me trouxer, geralmente lá aparecerá uma mensagem mais amigável das exceptions que ocorreram naquele range de tempo do filtro (por isso é importante limitar o máximo possível tal range, quanto menor menos log gerado e mais fácil será encontrar o que você precisa):



terça-feira, 5 de julho de 2022

Implantando Pacotes automaticamente em SandBox - D365 F&O

 Na postagem anterior, expliquei como é feito o build e empacotamento através de um Pipeline no Azure. Mas dai vem a dúvida. - Eu vou ter que subir aquele pacote gerado pelo pipeline manualmente pelo LCS, me minha SandBox? A resposta é: Não!

Você precisará criar um Release no Azure DevOps. Para isso, importe o seguinte json em seu projeto no Azure DevOps:

{"source":2,"revision":34,"description":null,"createdBy":{"displayName":"Otavio Anaga","url":"https://spsprodsbr1.vssps.visualstudio.com/A56f87ddd-07a4-409d-8f49-f17f22b12cbb/_apis/Identities/774c7aa6-f081-6c47-beb5-22138886fbe7","_links":{"avatar":{"href":"https://dev.azure.com/ContosoD365/_apis/GraphProfile/MemberAvatars/aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3"}},"id":"774c7aa6-f081-6c47-beb5-22138886fbe7","uniqueName":"otavioanaga@Contoso.com.br","imageUrl":"https://dev.azure.com/ContosoD365/_apis/GraphProfile/MemberAvatars/aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3","descriptor":"aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3"},"createdOn":"2021-10-23T18:02:00.000Z","modifiedBy":{"displayName":"Otavio Anaga Anaga","url":"https://spsprodsbr1.vssps.visualstudio.com/A56f87ddd-07a4-409d-8f49-f17f22b12cbb/_apis/Identities/774c7aa6-f081-6c47-beb5-22138886fbe7","_links":{"avatar":{"href":"https://dev.azure.com/ContosoD365/_apis/GraphProfile/MemberAvatars/aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3"}},"id":"774c7aa6-f081-6c47-beb5-22138886fbe7","uniqueName":"otavioanaga@Contoso.com.br","imageUrl":"https://dev.azure.com/ContosoD365/_apis/GraphProfile/MemberAvatars/aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3","descriptor":"aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3"},"modifiedOn":"2022-07-05T20:58:06.397Z","isDeleted":false,"lastRelease":{"id":211,"name":"Release-211","artifacts":[],"_links":{},"description":"Triggered by Release to SandBox 22.07.05.1.","releaseDefinition":{"id":1,"projectReference":null,"_links":{}},"createdOn":"2022-07-05T08:43:57.910Z","createdBy":{"displayName":"Microsoft.VisualStudio.Services.TFS","url":"https://spsprodsbr1.vssps.visualstudio.com/A56f87ddd-07a4-409d-8f49-f17f22b12cbb/_apis/Identities/00000002-0000-8888-8000-000000000000","_links":{"avatar":{"href":"https://dev.azure.com/ContosoD365/_apis/GraphProfile/MemberAvatars/s2s.MDAwMDAwMDItMDAwMC04ODg4LTgwMDAtMDAwMDAwMDAwMDAwQDJjODk1OTA4LTA0ZTAtNDk1Mi04OWZkLTU0YjAwNDZkNjI4OA"}},"id":"00000002-0000-8888-8000-000000000000","uniqueName":"00000002-0000-8888-8000-000000000000@2c895908-04e0-4952-89fd-54b0046d6288","imageUrl":"https://dev.azure.com/ContosoD365/_apis/GraphProfile/MemberAvatars/s2s.MDAwMDAwMDItMDAwMC04ODg4LTgwMDAtMDAwMDAwMDAwMDAwQDJjODk1OTA4LTA0ZTAtNDk1Mi04OWZkLTU0YjAwNDZkNjI4OA","descriptor":"s2s.MDAwMDAwMDItMDAwMC04ODg4LTgwMDAtMDAwMDAwMDAwMDAwQDJjODk1OTA4LTA0ZTAtNDk1Mi04OWZkLTU0YjAwNDZkNjI4OA"}},"variables":{"Client":{"value":"Contoso"},"LCSEnvironmentId":{"value":"5780497e-254b-4b6e-8219-850d646e9918"},"LCsProjectId":{"value":"1533614"}},"variableGroups":[],"environments":[{"id":1,"name":"Build to LCS","rank":1,"owner":{"displayName":"Otavio Anaga","url":"https://spsprodsbr1.vssps.visualstudio.com/A56f87ddd-07a4-409d-8f49-f17f22b12cbb/_apis/Identities/774c7aa6-f081-6c47-beb5-22138886fbe7","_links":{"avatar":{"href":"https://dev.azure.com/ContosoD365/_apis/GraphProfile/MemberAvatars/aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3"}},"id":"774c7aa6-f081-6c47-beb5-22138886fbe7","uniqueName":"otavioanaga@Contoso.com.br","imageUrl":"https://dev.azure.com/ContosoD365/_apis/GraphProfile/MemberAvatars/aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3","descriptor":"aad.Nzc0YzdhYTYtZjA4MS03YzQ3LWJlYjUtMjIxMzg4ODZmYmU3"},"variables":{},"variableGroups":[],"preDeployApprovals":{"approvals":[{"rank":1,"isAutomated":true,"isNotificationOn":false,"id":1}],"approvalOptions":{"requiredApproverCount":null,"releaseCreatorCanBeApprover":false,"autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped":false,"enforceIdentityRevalidation":false,"timeoutInMinutes":0,"executionOrder":1}},"deployStep":{"id":2},"postDeployApprovals":{"approvals":[{"rank":1,"isAutomated":true,"isNotificationOn":false,"id":3}],"approvalOptions":{"requiredApproverCount":null,"releaseCreatorCanBeApprover":false,"autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped":false,"enforceIdentityRevalidation":false,"timeoutInMinutes":0,"executionOrder":2}},"deployPhases":[{"deploymentInput":{"parallelExecution":{"parallelExecutionType":0},"agentSpecification":{"identifier":"windows-latest"},"skipArtifactsDownload":false,"artifactsDownloadInput":{"downloadInputs":[]},"queueId":27,"demands":[],"enableAccessToken":false,"timeoutInMinutes":0,"jobCancelTimeoutInMinutes":1,"condition":"succeeded()","overrideInputs":{}},"rank":1,"phaseType":1,"name":"Agent job","refName":null,"workflowTasks":[{"environment":{},"taskId":"31f040e5-e040-4336-878a-59a493355534","version":"1.*","name":"Initialize variable","refName":"","enabled":true,"alwaysRun":false,"continueOnError":false,"timeoutInMinutes":0,"retryCountOnTaskFailure":0,"definitionType":"task","overrideInputs":{},"condition":"succeeded()","inputs":{"Script":"#This simply exposes the Client parameter, required because of the way Task Groups expose variables to users of the group\n$tmp = \"$(Client)\"","ScriptArguments":""}},{"environment":{},"taskId":"78a30d98-c4a6-5ef0-b077-f3ef46c771d6","version":"0.*","name":"Upload $(Release.ReleaseName) - $(Build.BuildNumber) to project $(LcsProjectId)","refName":"","enabled":true,"alwaysRun":false,"continueOnError":false,"timeoutInMinutes":0,"retryCountOnTaskFailure":0,"definitionType":"task","overrideInputs":{},"condition":"succeeded()","inputs":{"serviceConnectionName":"efa96d8d-f51e-4081-a466-469ba3456f5f","projectId":"$(LcsProjectId)","assetType":"10","assetPath":"$(System.DefaultWorkingDirectory)/_Release to SandBox/drop/AXDeployableRuntime_$(Build.BuildNumber).zip","assetName":"$(Release.ReleaseName) - $(Build.BuildNumber)","assetDescription":"$(Release.ReleaseName) - $(Build.BuildNumber)","waitForValidation":"true"}},{"environment":{},"taskId":"31f040e5-e040-4336-878a-59a493355534","version":"1.*","name":"Get asset ID","refName":"","enabled":true,"alwaysRun":false,"continueOnError":false,"timeoutInMinutes":0,"retryCountOnTaskFailure":0,"definitionType":"task","overrideInputs":{},"condition":"succeeded()","inputs":{"Script":"$assetId= $env:LCSASSETUPLOAD_FILEASSETID\nWrite-Host(\"##vso[task.setvariable variable=AssetId;]$assetId\")","ScriptArguments":""}},{"environment":{},"taskId":"31f040e5-e040-4336-878a-59a493355534","version":"1.*","name":"Inline Powershell","refName":"","enabled":true,"alwaysRun":false,"continueOnError":false,"timeoutInMinutes":0,"retryCountOnTaskFailure":0,"definitionType":"task","overrideInputs":{},"condition":"succeeded()","inputs":{"Script":"Install-Module -Name 'MSAL.PS' -RequiredVersion '4.21.0.1' -AcceptLicense -Force","ScriptArguments":""}},{"environment":{},"taskId":"5852aa2c-30d2-517f-b766-bd37640e8a06","version":"2.*","name":"Deploy to sandbox2","refName":"","enabled":true,"alwaysRun":false,"continueOnError":false,"timeoutInMinutes":0,"retryCountOnTaskFailure":0,"definitionType":"task","overrideInputs":{},"condition":"succeeded()","inputs":{"serviceConnectionName":"efa96d8d-f51e-4081-a466-469ba3456f5f","projectId":"$(LcsProjectId)","environmentId":"$(LCSEnvironmentId)","fileAssetId":"$(assetId)","releaseName":"$(Release.ReleaseName) - $(Build.BuildNumber)","waitForCompletion":"false"}}]}],"environmentOptions":{"emailNotificationType":"OnlyOnFailure","emailRecipients":"release.environment.owner;release.creator","skipArtifactsDownload":false,"timeoutInMinutes":0,"enableAccessToken":false,"publishDeploymentStatus":true,"badgeEnabled":false,"autoLinkWorkItems":false,"pullRequestDeploymentEnabled":false},"demands":[],"conditions":[{"name":"ReleaseStarted","conditionType":1,"value":""}],"executionPolicy":{"concurrencyCount":1,"queueDepthCount":0},"schedules":[],"currentRelease":{"id":211,"url":"https://vsrm.dev.azure.com/ContosoD365/86984b62-8527-44d3-a2bc-d4c80f907df1/_apis/Release/releases/211","_links":{}},"retentionPolicy":{"daysToKeep":30,"releasesToKeep":3,"retainBuild":true},"processParameters":{},"properties":{"BoardsEnvironmentType":{"$type":"System.String","$value":"unmapped"},"LinkBoardsWorkItems":{"$type":"System.String","$value":"False"}},"preDeploymentGates":{"id":0,"gatesOptions":null,"gates":[]},"postDeploymentGates":{"id":0,"gatesOptions":null,"gates":[]},"environmentTriggers":[],"badgeUrl":"https://vsrm.dev.azure.com/ContosoD365/_apis/public/Release/badge/86984b62-8527-44d3-a2bc-d4c80f907df1/1/1"}],"artifacts":[{"sourceId":"86984b62-8527-44d3-a2bc-d4c80f907df1:3","type":"Build","alias":"_Release to SandBox","definitionReference":{"artifactSourceDefinitionUrl":{"id":"https://dev.azure.com/ContosoD365/_permalink/_build/index?collectionId=8b14f745-7fe1-47eb-ac2d-527e8b5f453f&projectId=86984b62-8527-44d3-a2bc-d4c80f907df1&definitionId=3","name":""},"defaultVersionBranch":{"id":"","name":""},"defaultVersionSpecific":{"id":"","name":""},"defaultVersionTags":{"id":"","name":""},"defaultVersionType":{"id":"latestType","name":"Latest"},"definition":{"id":"3","name":"Midnight Schedule - MS Hosted Agent Pipeline-import"},"definitions":{"id":"","name":""},"IsMultiDefinitionType":{"id":"False","name":"False"},"project":{"id":"86984b62-8527-44d3-a2bc-d4c80f907df1","name":"Dynamics 365"},"repository":{"id":"","name":""}},"isPrimary":true,"isRetained":false}],"triggers":[{"artifactAlias":"_Release to SandBox","triggerConditions":[],"triggerType":1}],"releaseNameFormat":"Release-$(rev:r)","tags":[],"properties":{"DefinitionCreationSource":{"$type":"System.String","$value":"ReleaseNew"},"IntegrateBoardsWorkItems":{"$type":"System.String","$value":"False"},"IntegrateJiraWorkItems":{"$type":"System.String","$value":"false"}},"id":1,"name":"Apply Package on SandBox","path":"\\","projectReference":null,"url":"https://vsrm.dev.azure.com/ContosoD365/86984b62-8527-44d3-a2bc-d4c80f907df1/_apis/Release/definitions/1","_links":{"self":{"href":"https://vsrm.dev.azure.com/ContosoD365/86984b62-8527-44d3-a2bc-d4c80f907df1/_apis/Release/definitions/1"},"web":{"href":"https://dev.azure.com/ContosoD365/86984b62-8527-44d3-a2bc-d4c80f907df1/_release?definitionId=1"}}}

Importe através do botão representado na imagem abaixo:


Na aba de variáveis, serão 3:




Client - é o tenant da empresa. Por exemplo, otavioanaga@contoso.com.br o tenant seria contoso

LCSEnvironmentId - é a guid do ambiente que receberá a release. Ela está disponível no LCS, na aba Manage Enviroment campo Enviroment Id

LCSProjectId - Acesse o projeto via LCS. O id do projeto é o número no final da URL.

Volte para a aba pipeline e configure o Artifacts:

É no Artifacts que referenciamos aquele pacote gerado pelo nosso pipeline. Delete o Artifact que veio com o arquivo e crie novamente através do botão Add, a configuração deve ser parecida com a imagem abaixo:



Importante: Certifique-se de que o Source Alias exibido nesta tela esteja contido na propriedade File to Upload do passo de upload contido na aba Tasks.





Uma vez configurado o Artifact, selecione o  e verifique o status da opção abaixo. Se ela estiver habilitada, então TODO build do pipeline configurado no passo anterior que ocorrer com sucesso, chamará o seu Release, então vai de você julgar se isso cabe no seu planejamento ou não:




Com tudo devidamente parametrizado, para testar basta ir até à pagina de releases no Azure Devops e selecionar Create a Release






Lembrando que só é possível implantar pacotes automaticamente em ambiente Sandbox. Em ambiente produtivo isso ainda não é possível. 

Quaisquer dúvidas é só postar na área de comentários.

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!