Configurar la exportación de Entity Store a Azure Data Lake

Empezar este post es fácil, porque muchos nos podemos preguntar:

¿Qué es un Data Lake?

Pescando en un Data Lake. Cortesía de cazapelusas.

Un Data Lake no es un producto de Azure, es un concepto que hace referencia a un lugar donde se guardan datos, sin importar si son estructurados o no. Su único propósito es guardar los datos sin procesar para que estén listos para ser consumidos por otros sistemas. Es como un lago que recibe y almacena el agua de sus afluentes, solo que con datos en vez de agua.

En Azure el Data Lake es un blob que guarda los datos. Y estos datos pueden venir de Microsoft Dynamics 365 for Finance o Supply Chain Management (voy a acabar loco con los cambios de nombre de Axapta 7) o de otros orígenes.

Actualmente, y desde el PU23, #MSDyn365FO (#MSDyn365F ? o #MSDyn365SCM ?) soporta oficialmente la exportación del Entity Store a un Azure Data Lake storage Gen1, pero la compatibilidad con el Data Lake Storage Gen2 está en preview privada con los Data Feeds, que nos permitirán exportar entidades y tablas (SÍ!) en casi tiempo real. Si queréis saber más echadle un ojo al grupo Data Management, Data Entities, OData and Integrations de Yammer del Insider Program (y si no estáis apuntados, deberíais).

Comparación vs. BYOD

Lo primero de lo que nos vamos a dar cuenta es el precio. El almacenamiento es más barato que una base de datos, incluso si es una sola base de datos en una instancia SaaS en Azure SQL. Por ejemplo, un Blob de 1GB en Azure cuesta 18.22€ al mes.

Y la DB más simple, una Azure SQL Gen 4 con 1 vCore cuesta 160,53€ al mes. Casi 10 veces más.

¿Y el redimiento? Esto que voy a decir es una conclusión de la observación, no un test real de rendimiento, pero los datos se transfieren muy rápido. Y es rápido porque en un Data Lake los datos se mandan sin procesar, no hay transformación de los datos hasta que se consumen (ETL para una DB, ELT para un Data Lake) así que se pierde menos tiempo hasta que los datos llegan a su destino. Esto no tiene un impacto real con conjuntos de datos pequeños, pero sí con los grandes.

Configuración

El proceso para exportar el Entity Store al Data Lake es bastante sencillo y está bien documentado (pero no actualizado del todo) en los docs. Lo explicaré paso a paso.

Crear una cuenta de almacenamiento en Azure

En Azure vamos a las cuentas de almacenamiento y creamos una nueva como en la imagen inferior:

Nos aseguramos de deshabilitar el almacenamiento Gen2:

Y ya podemos crear la cuenta. Cuando esté lista vamos a Access Keys y copiamos la cadena de conexión:

Azure Key Vault

El siguiente paso es crear el Key VAult. Para este paso debemos seleccionar la misma región que la de nuestra instancia de Dynamics 365:

Cuando el Key Vaul esté listo vamos al recurso y creamos un nuevo secreto. Pegaremos la cadena de conexión de la cuenta de almacenamiento y pulsamos crear:

Crear un registro de App de AAD

Le damos un nombre a la App, seleccionamos los tipos de cuenta soportadas que necesitemos y rellenamos la URL con la dirección de nuestra instancia de #MSDyn365FO:

La registramos y ahora tenemos que añadir la API de Azure Key Vault para la app como en la imagen:

Seleccionamos la API y añadimos el permiso delegado de user_impersonation:

No os olvidéis de dar permisos con el botón de encima (debe hacerlo un admin de Azure). Ahora vamos a los secretos, creamos uno y copiamos el valor que nos da. Cuando se cierre esta pestaña no podremos ver el valor del secreto, así que aseguráos de haberlo copiado!

Configurar el Key Vault

Volvemos al Key Vault que hemos creado antes y vamos a Access policies. Creamos una nueva:

Necesitamos seleccionar Get y List para permisos de clave y secreto:

Pulsamos select principal y aquí añadimos la App de AAD que hemos creado en el tercer paso:

Añádela y no te olvides de darle a guardar en la página de las políticas de acceso!!

Configurar MSDyn365F… y O o SCM o como sea que se llame este mes

Vamos a Administración del sistema -> Configurar -> Parámetros del sistema y ahí a la pestaña Conexiones de datos. Aquí tenemos 4 campos que hay que rellenar. El Application ID es el Application ID de la App de AAD (obvio) y el Application Secret  el secreto de esa App. Esta parte está bastante clara.

El DNS name es la URL del Key Vault, y el Secret name es el nombre del secreto que hemos creado en el Key Vault con la cadena de conexión.

Una vez está todo configurado podemos pulsar los botones de prueba y, si habéis seguido todos los pasos, deberían saliros estos mensajes:

Si cualquiera de las validaciones falla simplemente borraría todos los recursos y empezaría de cero.
Ahora, los dos checkbox que tenemos al lado de los campos:
  • Enable Data Lake integration: activa el push de datos del entity store a la cuenta de almacenamiento que hemos creado al principio y que es el principal propósito de este post.
  • Trickle update Data Lake: hace actualizaciones después de que cambien los datos (Trickle Feed).

Configurar Entity Store

Para acabar, vamos al Entity Store (en Administración del sistema-> Configurar -> Entity Store) y activamos el refresco de las entidades que queremos que hidraten el Data Lake (me encanta, parece que es el término correcto para referirse a mandar datos al Data Lake):

Y listo, nuestros datos se están mandando a un Blob de Azure:

Las entidades se guardan cada una en una carpeta, y dentro de cada carpeta hay otra carpeta por cada medida de esa entidad, y dentro un CSV con los datos.

Ahora podemos consumir estos datos desde Power BI con el conector de blob, o alimentar a Azure Data Factory o lo que quieras, porque ese es el propósito del Data Lake.

Configurar las nuevas tareas de Azure DevOps para generar el paquete y versiones de modelos

Durante la pasada noche (que por lo menos era noche para mí :P) se han publicado las nuevas tareas de Azure DevOps para desplegar los paquetes, actualizar versiones de modelos y añadir licencias a los DPs:

Se ha publicado tambien un anuncio en los blogs de Community con más detalles acerca de la configuración. Vamos a ver las nuevas tareas y cómo configurarlas.

Tarea Update Model Version

Esta es sencillita, simplemente hay que añadirla a tu definición de build debajo de la tarea actual, deshabilitas la original y listo. Si tienes algún filtro, excluyendo modelos por ej., necesitaras crear el filtro en el campo Descriptor Search Pattern usando la sintaxis de patrones de Azure DevOps.

Tarea Create Deployable Package

Esta tarea va a sustituir la Generate packages actual. Para configurarla correctamente necesitamos hacer un par de cambios a los valores que trae por defecto:

X++ Tools Path

Esto es el directorio físico de tu VM de build donde está la carpeta bin. La carpeta AosService normalmente está en la unidad K en las VMs desplegadas en la suscripción del cliente. Probablemente esto cambie cuando pasemos a un modelo sin VMs para hacer las builds.

Edito!: la ruta a la unidad se puede cambiar por $(ServiceDrive), quedando una ruta como $(ServiceDrive)\AOSService\PackagesLocalDirectory\bin.

Location of the X++ binaries to package

La tarea viene con este campo rellenado con $(Build.BinariesDirectory) por defecto, pero esto no nos ha funcionado para nuestras builds, quizás esa variable no esta en el archivo proj. Sólo hay que cambiarlo por $(Agent.BuildDirectory)\Bin y el DP se generará sin problemas.

Filename and path for the deployable package

La ruta en la imagen debería cambiarse por $(Build.ArtifactStagingDirectory)\Packages\AXDeployableRuntime_$(Build.BuildNumber).zip. Se puede dejar sin la parte de Packages pero entonces habra que cambiar el campo Path to Publish de la tarea Publish Artifact: Package de la definición.

Tarea Add Licenses to Deployable Package

Esta tarea añade las licencias a un Deployable Package que ya existe. Recuerda que la ruta del DP tiene que ser la misma que hayas configurado en la tarea Create Deployable Package.

¡Y ya esta todo listo! Un pasito más cerca de deshacernos de las VM de build.

Si necesitas ayuda para configurar Configurar Release en Azure DevOps puedes leer este post que escribí.

 

Usando Azure Application Insights con MSDyn365FO

Primero de todo… AVISO: antes de usar esto en un entorno de producción pensadlo bien. Y luego volvedlo a pensar. Y si finalmente decides usarlo, hacedlo con cuidado y cariño.

Por qué este aviso? Bueno, a pesar de que los documentos aseguran que la afectación en el rendimiento del sistema en general es mínima hay que andar con cuidado. Es un ERP. Uno en el que no tenemos acceso al entorno de producción (a no ser que estéis On-Prem) para analizar si hay impacto. Además probablemente Microsoft ya está usandolo para recoger datos de los entornos y mostrarlos en LCS, y desconozco si puede haber interferencias. Un montón de no-lo-ses.

Lo usaría en producción? . Puede ser muy útil en algunos casos.

Y dicho esto, de qué voy a escribir que necesita un aviso? Como dice el título, sobre usar Azure Application Insights en Microsoft Dynamics 365 for Finance and Operations. Este post es consecuencia de uno de los «Has visto esto? Sí, deberíamos probarlo!» entre Juanan (aquí en Twitter, seguidle!) y yo. Y el esto esta vez era este post de Lane Swenka en AX Developer Connection. Así que nada original por aquí 🙂

Azure Application Insights

I spy
Made by Cazapelusas

¿Y qué es Application Insights? Como dice la documentación:

Application Insights is an extensible Application Performance Management (APM) service for web developers on multiple platforms. Use it to monitor your blah web application. It will blah blah detect blaaah anomalies. It blah powerful blahblah tools to bleh blah blih and blah blah blaaaah. It’s blaaaaaaaah.

Mmmm… ved este vídeo mejor:

Hay tanta miseria y tristeza en los primeros 30 segundos…

Monitoreo. Eso hace y para eso es. «Eh, pero LCS ya hace eso!«. Vale, monitoreo extra! A todo el mundo le gusta lo extra, como la pizza, excepto si es piña, claro.

Haciendo que funcione

El primer paso será crear un recurso para Application Insights en nuestra suscripción de Azure. Sobre el precio: los 5 primeros gigas por mes son gratuitos, y los datos se guardan durante 90 días. Más información aquí.

Después necesitamos el código. Me voy a ahorrar los detalles en esta parte porque está perfectamente explicado en el link que he puesto antes (este). Básicamente tienes que crear una DLL para manejar los eventos y mandar la información a AAI y usar esa DLL desde MSDyn365FO. En nuestra versión hemos añadido un método extra para trazas llamado trackTrace. Después solo hay que referenciar la DLL en 365 y ya lo podemos usar.

Qué podemos medir?

Ahora viene la parte interesante (espero). Visitas de páginas, capturar errores (o todos los infologs), ejecuciones de lotes, cambios de valor de campos, y cualquier cosa que podamos extender y desde ahí llamar a nuestra API.

Por ejemplo, podemos extender la clase FormDataUtil del motor de formularios. Esta clase tiene varios métodos que se llaman desde los formularios en acciones de los datasources, como validaciones de writes, deletes, campos, etc… Y también esto:

modifiedField in FormDataUtils

Este método se ejecuta cada vez que se modifica un campo en un formulario. Lo vamos a extender para registrar qué campo se ha modificado, el valor anterior y el nuevo. Así:

Extending modifiedField
Prometo que siempre uso etiquetas!

Y como la llamada a Application Insights también guarda el usuario que ha hecho el cambio de valor, tenemos un nuevo log de la base de datos! Incluso mejor, tenemos un nuevo registro de la base de datos que no afecta al rendimiento porque no se generan datos extra en MSDyn365FO. La única pega es que solo se llamará desde formularios, pero puede ser suficiente para monitorear el uso de formularios y los “yo no he tocado ningún parámetro!” 🙂

Esto es lo que vemos en el explorador de métricas de Azure Application Insights:

Azure Application Insights Custom Event
Qué quieres decir con que he tocado eso!?

Sí, fuiste tú usuario Admin! Uy si soy yo…

Custom events

Todas las métricas de los eventos se muestra  en Azure, y los datos se pueden mostrar en Power BI.

Repito, planead bien lo que queréis monitorear antes de usar esto y testeadlo. Luego testeadlo otra vez, sobretodo en entornos SAT con bases de datos Azure SQL. Tienen un rendimiento distinto a un SQL Server normal y hay que estar seguro.

A disfrutar de los datos!

Dynamics 365 for Finance & Operations y Azure DevOps (parte II)

En la primera parte de este post vimos a importancia de Azure DevOps y como configurarlo para MSDyn365FO.

Quiero empezar esta segunda parte con una pequeña pataleta. Como decía en la primera parte, los que llevamos años trabajando con AX nos habíamos acostumbrado a no usar un control de versiones. MSDyn365FO nos ha llevado a un terreno sin explorar, con lo que no es raro que cada equipo haya decidido trabajar de una forma u otra según las experiencias que se hayan ido encontrando. Evidentemente, hay un componente del interés de los miembros de estos equipos para investigar un poco por su cuenta sobre la gestión de código, ramas y metodologías. Muchas veces a base de experimentación y prueba-error, y con las prisas de algunos proyectos esto sale mal, o muy mal. Y aquí he echado de menos un poco de guidance por parte de Microsoft (que igual la hay y me lo he perdido).

A pesar de esta quejita el camino y el aprendizaje ha sido, y creo que lo que viene también será, bastante divertido 😉

Estrategias de branching

Vaya por delante que no soy, ni mucho menos, un experto en gestión del código ni Azure DevOps. Todo lo que viene a continuación es fruto, como comentaba antes, de la experiencia (y las meteduras de pata) de casi 3 años trabajando con MSDyn365Ops. En este artículo de la documentación sobre estrategias de branching hay más información sobre branching y links a artículos del equipo de DevOps. Y en la Biblioteca de herramientas y guías de los DevOps Rangers hay incluso muchísimo más!

La verdad es que me encantaría una sesión de FastTrack sobre esto y, creo que no la hay. EDIT: parece que no lo vi y sí que existe una sesión de FastTrack sobre esto que se llama Developer ALM. Gracias a Dag Calafell (twitter) por la información!

Como vimos en la primera parte cuando desplegamos la máquina de Build se crea la carpeta de Main. Lo normal es que en un proyecto de implantación se desarrolle sobre Main hasta el momento del arranque, y que justo antes del go live se cree una branch (rama) de desarrollo. El árbol de código quedaría así:

Ramas despues de branch

En ese momento los mapeos de las máquinas de desarrollo deben cambiarse para que apunten a esta nueva rama de dev. Esto permitirá seguir desarrollando mejoras o corrigiendo errores y decidir el momento en el que se van a mover a producción haciendo un merge a Main.

Esta estrategia es bastante sencilla y que no provoca muchos quebraderos de cabeza. En mi anterior trabajo en cliente final decidimos usar 3 ramas por peculiaridades de la empresa. Main, Dev y Test con merges de Dev a Test y de Test a Main. Un dolor de cabeza al final, gestionar las 3 ramas, con upgrades de versiones, decenas de changesets pendientes y un partner ISV que no ayudaba mucho era bastante divertido.  ¿Pero, y lo que aprendí? Buf.

En cualquier caso un consejo: intentad evitar que se queden changesets pendientes de mergear durante mucho tiempo. La cantidad de conflictos que aparecen y hay que resolver a mano es directamente proporcional a lo viejo que sea el changeset.

Llegado a este punto no puedo hacer suficiente hincapié en lo de normal de más arriba. Como digo, esto lo escribo basado en mis experiencias. Está claro que no es lo mismo trabajar en un partner de implantación que en un ISV. Un ISV tiene la necesidad de mantener diferentes versiones de su producto y no va a usar una rama Main y otra Dev sinó que puede tener una (o varias) por versión a mantener para dar soporte a todos los clientes (aunque desde la 8.1 y el fin del overlayering ya no es necesario). Para más «ideas» el artículo que he enlazado al principio es perfecto para empezar.

Builds

En la primera parte y en otro post (Builds que no responden en Azure DevOps) expliqué un poco acerca de las builds. Ya vimos que la definición de build que se genera por defecto al desplegar el servidor es como la de la imagen inferior:

Pasos de la definición de build por defecto

Esta build tiene todos los pasos con los que se ha creado activos. Podemos desactivar (o borrar) los pasos que no necesitemos. Por ejemplo, los 3 de testeo si no tenemos tests creados, o la sincronización y despliegue de informes.

Podemos crear nuevas definiciones de build a partir de esta o de 0 (pero es más sencillo y rápido duplicar esta y modificarla) para que se apliquen a otras ramas u otros motivos.

Con la versión 8.1 de MSDyn365FO han desaparecido los hotfixes de código X++, todos son binarios. Esto lo que implica es que en la carpeta Metadata de nuestras ramas ya no van a aparecer los modelos del estándar, solo los nuestros. Hasta la versión 8.0 era muy útil tener una definición de build únicamente para nuestros modelos y otra con todos los modelos. Con esto lo que se consigue es tener un DP en mucho menos tiempo que generándolo para todos los modelos. Si se aplica algún hotfix hay que generar el DP de la rama con todos los modelos, pero si sólo hay código propio no hace falta generar un paquete con todos los modelos.

Y hasta aquí la información desactualizada. A estas alturas todos los proyectos deberían estar en 8.1 o listos para estarlo, que en abril llega One Version!

Otra opción que es bastante útil es que, por ejemplo, podemos crear una nueva definición que lo único que haga es compilar una rama:

Definicion build continua

Esta build no hace nada más, solo compila. Así a priori no parece muy útil pero si activamos la opción de integración continua:

DevOps continuous integration

Después de cada check-in de cada desarrollador se lanzará una build que compilará todo el código y fallará si hay algún error. ¿Claro que no debería fallar no? Porque todos compilamos los proyectos antes de hacer el check-in, ¿verdad?

tysonjaja

Pues por eso y porque las prisas son malas y a veces tenemos que vivir con ellas, esta build puede ser bastante útil. Sobretodo cuando lo tengamos configurado para la rama Main y nos «chive» los errores que pueden aparecer después de un merge con conflictos. Y cuando hay que pasar algo urgente a producción y tenemos poco margen nos interesa poder generar el paquete lo antes posible. Usando esta estrategia conseguimos que generar un DP con nuestros paquetes tardara 9 minutos en vez de 1h15m generando todo.

Igual alguien con más conocimiento de esto piensa, pero eso no lo puedes hacer con…

Gated check-ins

Con este tipo de check-in el código se compila ANTES de que el check-in se haga efectivo. Si falla la build el changeset no se hace efectivo hasta que se corrijan los errores y se vuelva a hacer el check-in.

A priori esta opción parece ideal para los check-in de merges de una rama de desarrollo a Main. Los problemas que me he encontrado con esta opción son varios:

  • Si haces múltiples merge y check-ins de un mismo desarrollo y el primero falla no se mergea, pero si el segundo compila correctamente sí.
  • Problemas con las notificaciones de errores y código pendiente al fallar el check-in
  • En merges con más de un check-in se encolan muchas builds (y por defecto solo tenemos un build agent disponible…)

Seguro que esto tiene solución, pero no he sabido encontrarla. Y de todas formas la opción de integración contínua que comentaba antes nos ha funcionado perfectamente para validar que la rama compila sin errores. Como digo todo esto ha sido fruto de la investigación del equipo y prueba-error.

Conclusiones

Supongo que la mayor conclusión es que con MSDyn365FO hay que usar Azure DevOps. Es obligatorio, no hay otra opción. Los que no lo estéis haciendo, si es que alguien no lo hace, hacedlo. Ya. Revisad vuestra forma de trabajo y olvidemos de una vez por todas AX, MSDyn365FO a nivel técnico es otro producto.

La verdad es que, a los desarrolladores, MSDyn365FO nos ha acercado un poco más a lo que es un proyecto de desarrollo de software clásico como puede ser uno de .NET o Java. Pero no del todo. Un proyecto de ERP tiene muchas peculiaridades, y creo que no partir de zero en el desarrollo del producto, tener una base que nos «obliga» un poco a seguir una línea, nos limita en algunos aspectos y en el uso de ciertas técnicas y metodologías.

Y hasta aquí estos dos posts sobre Azure DevOps. Espero que le sean de ayuda a alguien. Y si alguien con más experiencia, o mejores ideas, quiere recomendar algo, ¡los comentarios están abiertos!

Dynamics 365 for Finance & Operations y Azure DevOps (parte I)

Con la llegada de Dynamics 365 el uso de un sistema de control de versiones se ha convertido en obligatorio. En anteriores versiones disponíamos de Morph VCS en AX 2009 y la posibilidad de integrar TFS en AX 2009 y AX 2012 (del que hay un completo curso en El rincón Dynamics), pero no existía ninguna obligación de usar ninguno de los dos. En realidad, siempre según mi experiencia, creo que la mayoría de proyectos se llevaban a cabo sin ningún tipo de control de versiones aparte de, con suerte, comentarios en el código.

El AOT antes de la llegada del control de versiones
El AOT antes de la llegada del control de versiones, de cazapelusas.com

Azure DevOps en MsDyn365FO

En Microsoft Dynamics 365 for Finance and Operations el control de versiones que nos ofrece Azure DevOps no es un simple control de versiones, sino una LA herramienta que hará un poco de Anillo Único en nuestros proyectos (solo que, espero, no para atarnos en las tinieblas). Y es que el cambio no solo afecta al equipo técnico. Desde dirección de proyecto a funcionales pueden implicarse en el uso de Azure DevOps para la gestión del proyecto.

La sincronización del BPM y creación de todas las tareas, planificación del equipo, gestión del código, builds automatizadas y releases que veíamos en un post anterior, son algunas de las herramientas que nos ofrece. Todos estos cambios requieren de un aprendizaje y adaptación por parte del equipo al completo, pero van a ayudarnos mucho en el control del proyecto.

Como decía, puede parecer que el equipo técnico sea el más afectado por la introducción de Azure DevOps por la «obligatoriedad» de usarlo en Visual Studio (bendita obligación), pero también es el que más provecho le va a sacar… 😉

Primeros pasos

Lo primero que tenemos que hacer cuando empezamos un nuevo proyecto de implantación es conectar LCS y el proyecto de Azure DevOps que vayamos a usar. Está todo muy bien explicado en la documentación.

Una vez configurada la conexión tenemos que desplegar el entorno de Build que vimos en el anterior post. Esto se hace habitualmente en la máquina de desarrollo disponible en la suscripción de Microsoft en el proyecto de LCS. Cuando se despliega esta máquina se va a crear la estructura básica de carpetas en el proyecto de DevOps:

Carpetas en proyecto de Azure DevOps

(Ignorad la carpeta CSProjects que es de la actuación cómica del pasado 365 Saturday con mi compañero Juanan)

Con esto ya podemos mapear las máquinas de desarrollo y empezar a trabajar. La carpeta Main que veis en la imagen es una carpeta normal, pero la podremos convertir en una rama en caso de que lo necesitemos.

Carpeta convertida en rama

En la imagen de arriba podemos ver que el icono de Main cambia cuando se convierte en una rama. Las ramas (branches en inglés) nos ofrecen funcionalidades que no están disponibles en las carpetas. Lo podemos ver en el menú contextual:

Menú contextual carpeta
Menú contextual carpeta
Menú contextual rama
Menú contextual rama

Por ejemplo en las ramas podemos ver la jerarquía de las distintas ramas del proyecto (En este caso que sólo trabajamos con dos ramas no parece muy útil :P).

Jerarquía de las ramas

También son distintas las ventanas de propiedades de ambas. Las de una carpeta:

Y las propiedades de una rama, donde podemos ver las relaciones y las ramas que se han creado a partir de ella:

Propiedades de la rama

Todo esto son detallitos, pero quizás lo que mas nos interese de convertir Main en una rama es que nos permitirá ver dónde se ha mergeado qué, como veremos en un próximo post 😛

Un consejo

La carpeta de Projects es buena idea ponerla en la raíz del proyecto de DevOps (al mismo nivel que BuildProcessTemplates y Trunk). Si no se cambia y acabáis trabajando con una rama de dev y la de Main, los check-in de las soluciones y proyectos de Visual Studio se seguirán haciendo en Main (porque la carpeta de proyectos estará ahí). Os ahorrará microinfartos cuando veáis la lista de changesets en el correo de la build de Main 🙂


Y hasta aquí la primera parte del tema. En el próximo post voy a intentar explicar la estrategia de branching que podemos usar en los proyectos y definiciones de build que nos pueden ser útiles.

Builds que no responden en Azure DevOps

Se puede dar el caso de que al lanzar una build no empiecen a procesarse las tareas. Intentas cancelar esa build y… tampoco se cancela. El servidor de build no responde. Pruebas a reiniciar la VM de build y nada. Este caso puede ser un poco raro pero puede pasar.

El servidor de build

El servidor de build es una máquina un poco distinta a las demás de Microsoft Dynamics 365 for Finance and Operations. Aparentemente es exactamente igual que una VM de desarrollo, tiene Visual Studio, tiene un AosService/PackagesLocalDirectory con los modelos y XML de los objetos del AOT, un servidor de SQL y una AxDB y todos los servicios que usa MSDyn365FO (MR, Batch y IIS/IIS Express).

Pero no usamos nada de eso. El «corazón» del servidor de build en realidad es el build agent, una aplicación a la que accede Azure DevOps para realizar algunas de las tareas de cada build. Esto se enlaza al configurar el proyecto de DevOps en LCS como veremos en otro post 😉

Como curiosidad decir que en el futuro no tendremos este servidor sinó bastará con Azure DevOps. He estado buscando la fuente de esto pero no la encuentro, pero creo recordar que Joris de Gruyter lo comentó en Twitter. Si lo encuentro lo voy a linkear.

Edit: sigo sin encontrarlo, pero en este tuit lo deja caer.

El problema

Al final hay poco misterio y todo se ha ocasionado por tener 2 agentes de build configurados en nuestro pool. ¿Cómo ha pasado? Bueno, en nuestro caso, ha sido porque durante un espacio de tiempo muy corto han convivido 2 proyectos de LCS configurados contra el mismo proyecto de Azure DevOps. Es raro sí, tiene una explicación y no ha sido por ningún tipo de chapuza 😉

Esto ha hecho que pasara lo que podéis ver en la imagen:

Dos agentes de build para el mismo proyecto y pool!

Hay dos agentes a la vez y, encima, el que está marcado como activo está offline! Este agente es el del primer proyecto de LCS que se usó, y a pesar de que ya habíamos marcado el correcto como activo se volvió a cambiar solo.

La solución es tan sencilla como conectarse con un administrador de la cuenta de DevOps (no del proyecto en el que estemos), expandir la sección de agentes y borrar el agente offline con la X. Marcar el correcto como activo y ya se retomarán las builds con toda normalidad.

Borrando el agente offline de Azure DevOps

Y nada más, un problema menos.

Configurar Release en Azure DevOps para Dynamics 365 for Finance and Operations

Vamos allá…

Hace unas semanas se publicó en el Marketplace de Azure DevOps la extensión para releases de #MSDyn365FO, con lo que nos acercamos un poco más al escenario de la integración continua. A falta de la documentación oficial tenemos las notas en el anuncio que se hizo, pero vamos a ver paso a paso como configurar todo lo que hace falta para que funcione en nuestro proyecto.

Para configurar el release necesitaremos lo siguiente:

  • Aplicación de AAD
  • Datos del proyecto de LCS
  • Un proyecto de Azure DevOps que esté vinculado al anterior de LCS
  • Usuario tipo cuenta de servicio

Al usuario es recomendable que no le caduque la contraseña (de ahí la cuenta de servicio) y que tenga permisos suficientes tanto en LCS, Azure y Azure DevOps. Esto no es obligatorio, se puede configurar con un usuario normal para hacer pruebas sin ningún problema.

Crear la app de AAD

El primer paso es crear una aplicación de Azure Active Directory para poder subir el paquete generado por la build a LCS, así que nos dirigiremos al portal de Azure y una vez nos hayamos logueado iremos a Azure ActiveDirectory, luego a App Registrations y crearemos una nueva de tipo Native:

Nueva app azure AD

A continuación vamos a «Settings» y «Required permissions» y añadimos la API de Dynamics Lifecycle Services:

Permiso de LCS

Seleccionamos el único permiso disponible en el paso 2 y aceptamos hasta que aparezca el nuevo permiso en la sección «Required permissions». En este paso nos falta únicamente pulsar en «Grant permissions» para que se apliquen los cambios:

Grant permission

Sin este último paso la subida a LCS no se podrá realizar. Una vez hemos hecho esto guardamos el Application ID para usarlo más adelante.

Crear release en Azure DevOps

Antes de configurar nada en Azure DevOps tenemos que asegurarnos que el proyecto que vamos a usar esté vinculado en LCS. Esto lo podemos comprobar en el apartado de «Visual Studio Team Services» en la configuración del proyecto de LCS.

Una vez comprobado esto crearemos la definición de release en DevOps desde Pipelines -> Releases. Seleccionamos «New release pipeline» y del listado que aparece elegimos el «Empty job».

Primero de todo asignaremos a qué build irá vinculada esa definición de release desde «Add an artifact»:

New release

En «Source» seleccionamos la definición de build que queremos usar, en «Default version» usaremos «Latest» y pulsamos «Add».

El siguiente paso es definir la Task con la extensión de release para Dynamics. Pulsamos en la pestaña Tasks y en el botón «+». Nos aparecerá una lista y buscaremos «Dynamics 365 Unified Operations Tools»:

Dynamics 365 Unified Operations Tools

Si no hemos añadido la extensión previamente lo podemos hacer desde esta misma pantalla. Para poderla añadir el usuario con el que estemos creando la release tiene que ser administrador de la cuenta de Azure DevOps en la que esté el proyecto, no es suficiente con que lo sea del proyecto.

Una vez añadida la tarea tenemos que rellenar una serie de parámetros:Release Dynamics Operations

Crear la conexión a LCS

El primer paso es crear la conexión a LCS con la aplicación de AAD que hemos creado antes. Pulsamos New y se abrirá la siguiente ventana:

Coenxión LCS Azure DevOps

Sólo es necesario rellenar el nombre, usuario, contraseña y el Application (Client) ID con el App ID que tenemos del paso inicial en Azure, los campos de «Endpoint» deberían completarse solos. Pulsamos OK y ya tenemos la conexión lista.

En el campo LCS Project Id ponemos el ID que aparece en la URL del proyecto de LCS, por ej. en https://lcs.dynamics.com/V2/ProjectOverview/1234567 el Id es 1234567.

Pulsamos el botón al lado del campo de «File to upload» y seleccionaremos el archivo del deployable package que genera la build:

DP Generado

Dependiendo de si habéis modificado la definición de build o no, el archivo tendrá un nombre u otro, pero normalmente es del tipo AXDeployableRuntime_VERSION_NUMEROBUILD.zip. Cambiad el número fijo de build por la variable de la siguiente manera:

BUildNumber

En «LCS Asset Name» y «LCS Asset Description» se define el nombre y descripción que tendrá el paquete en LCS. Para estos campos podéis usar todas las variables predefinidas de build y de release que ofrece Azure DevOps. Siguiendo con el caso anterior del nombre del archivo, usaremos un prefijo que describa qué tipo de paquete es (para producción o pre-producción) seguido de $(Build.BuildNumber), generando por ejemplo un DP llamado Prod 2019.1.29.1 con la fecha de build.

Ahora ya sólo nos queda guardar y probar. En la pantalla de Releases seleccionamos la que acabamos de crear, le damos al botón «Create a release» y sin cambiar ninguna opción seleccionamos OK en la pantalla que se ha abierto. Se lanzará la release y si todo va bien podremos ver el paquete en LCS:

LCS Asset Library

Si queremos automatizar la parte de release y que se ejecute cada vez que termine una build sólo tenemos que activar el trigger en el artefacto:

Release trigger

Desde el botón del rayo se nos abre un diálogo y simplemente hay que marcar la opción que aparece.

Nada más, con estos pasos ya tendremos configuradas las builds (que pueden estar automatizadas también) y los releases. Sólo falta que los despliegues también se puedan automatizar y ya estaremos en la integración continua que comentaba al principio.