jueves, 7 de julio de 2016

Publicar WebJob con WebDeploy

Los websites de Azure (o como quiera que se llamen ahora) son un buen invento. Se publican fácilmente desde Visual Studio y tienen un montón de opciones útiles, entre ellas los WebJobs. Sin embargo, después de crear un slot de staging, algo no funcionaba como esperaba en relación al WebJob. El problema era que el WebJob no formaba parte del proyecto, es decir, se estaba creando a mano desde el portal de Azure y sólo se había hecho inicialmente en “production”, con lo que al hacer el swap de “staging” a “production” se estaba perdiendo y al volver a publicar en staging desde Visual Studio no se agregaba… resultado, un WebJob desaparecido en combate porque forma parte del slot.

Una solución sería crear el WebJob manualmente en ambos entornos (“staging” y “production”) y no olvidar activar la opción “Exclude files from the App_Data folder” durante la publicación a través de Web Deploy (un WebJob se guarda en el directorio App_Data). En cualquier caso, realmente el problema es no haber tratado al WebJob como parte del proyecto. Muy clarificador al respecto esta respuesta en stackoverflow http://stackoverflow.com/a/31079730 “Note it is a bad practice to deploy a WebJob directly and not as part of your website files/repository, this is probably the cause of issues you are having.”

Está claro, el WebJob debe ser parte del proyecto.

Si el WebJob es una aplicación de consola hubiera seguido esta guía https://azure.microsoft.com/en-us/documentation/articles/websites-dotnet-deploy-webjobs/ pero el WebJob es Node.js (que tampoco sé si habrá algo de serie para facilitar la vida, pero en una lectura rápida parecería más orientado sólo a aplicación de consola, lo mismo en 2 días me desdigo…).

Finalmente, la pregunta es ¿Cómo hacer que en App_Data esté el WebJob preparado para su publicación a través de Visual Studio? Pues con nuestro amigo MSBuild.

En mi caso he optado por agregar código al fichero .pubxml (publicación).

Primero, restaurar los paquetes de Node, invocando un target antes de la publicación http://stackoverflow.com/a/12920499

  
    
      CustomBeforePublish;
      $(PipelineDependsOn);
    
  
  
    
  

La verdad es que esto se podría haber evitado usando Grunt, Gulp o similar, que está perfectamente integrado con Visual Studio, pero sólo quería tener la carpeta node_modules cuando fuera a publicar, no antes.

En cualquier caso, con esto me aseguro de que todas las dependencias están ahí, porque lógicamente no pienso en agregar estos ficheros al .csproj ni subirlos al control de código fuente ni nada de eso.

Segundo (y porque la carpeta node_modules no está incluida en el .csproj), copiar estos ficheros en el paquete de publicación http://www.hackthedot.dk/2012/10/adding-extra-files-to-deployment.html

  
    
      
      
        App_Data\jobs\triggered\MyWebJob\node_modules\%(RecursiveDir)%(Filename)%(Extension)
      
    
  
  
    
      IncludeNodeModules;
      $(CopyAllFilesToSingleFolderForPackageDependsOn);
    
  

Con esto se ha salvado la papeleta, ahora el WebJob forma parte del proyecto y la publicación lo tiene en cuenta.

Para “staging”, agregando la variable de entorno WEBJOBS_STOPPED con el valor 1 me aseguro que en “staging” no se va a ejecutar el WebJob https://github.com/projectkudu/kudu/wiki/Web-jobs#configuration-settings

Claro está que no parece la mejor opción, lo suyo sería menos MSBuild, más tarea Exec y algún sistema de build de cliente, pero por ahora vale.

Un saludo!