Перейти к содержимому

Azure Web apps: автоматическое развертывание Drupal с фронтэнд компиляцией при помощи Grunt

Данная запись посвящена решению следующей задачи: автоматически развернуть веб приложение, основанное на Drupal, с компиляцией фронтэнда, использующей Grunt, при помощи Continuous Deployments фичи Web app (то есть, без выделенного билд сервера), при том, что доступ к серверу должен быть ограничен по IP.

Azure Web app использует для чекаута и доставки контента их репозитория в папку сайта (d:\home\site\wwwroot\), причём он достаточно умён, чтобы обнаружить, например, sln файл и вызвать MsBuild для компиляции. Помимо этого, мы можем самостоятельно формировать файл-инструкцию для при помощи файла .deployment в корне репозитория и инструкций в этом файле.

Самый простой способ, чтобы сформировать этот файл и стартовый набор инструкций в нём - это использовать azure-cli.
Устанавливаем azure-cli при помощи команды "npm install azure-cli -g"
Далее, создаём базовую структуру, выполнив в корне репозитория следующую команду: "azure site deploymentscript --" (для .js). Данная команда создаст 2 файла:

  • .deployment - файл инструкций для Kudu c указанием, какой файл выполнить после чекаута
  • deploy.cmd (для Win)/deploy.sh (для *nix)

Рекомендую освежить свои знания по консольным командам (Kudu достаточно умён, чтобы выполнять команды и cmd) и приступить к оптимизации скрипта в deploy.[cmd|sh] файле.

Ход выполнения таков:

  1. Kudu забирает данные из репозитория в папку d:\home\site\repository
  2. Kudu выполняет инструкции из .deployment файла в корне репозитория (если найдётся такой)
  3. Билд завершен

Во время обкатки я обнаружил, что дефолтная версия не подходит для моей компиляции. К счастью, это просто пофиксить:

  • Идём в консоль Kudu ( https://<sitename>.scm.azurewebsites.net ), выбираем cmd в Debug Console
  • Щёлкаем на изображение диска и переходим в D:\Program Files (x86)\nodejs
  • Тут мы увидим все доступные для нашего Azure Web app версии Node.js
  • Выбираем нужную и выставляем нужную версию в качестве значения для ключа WEBSITE_NODE_DEFAULT_VERSION

Вторая проблема, с которой я столкнулся, была в том, что grunt до сих пор использует слишком старую версию glob, что выражается в ошибке доставки: "Error: ENOTSUP: operation not supported on socket, scandir ".
Самый простой способ для меня был в том, чтобы вручную проапдейтить glob при помощи дополнительных команд в моём deploy.cmd:

pushd node_modules\grunt
call :ExecuteCmd !NPM_CMD! install glob@^6.0.4 --save
popd
pushd node_modules\grunt-modernizr\node_modules\customizr
call :ExecuteCmd !NPM_CMD! install glob@^6.0.4 --save
popd
pushd node_modules\customizr
call :ExecuteCmd !NPM_CMD! install glob@^6.0.4 --save
popd

Ограничение доступа по IP для Azure Web app делается при помощи элемента configuration/system.webServer/security/ipSecurity. Так как я пока не нашёл способа трансформировать web.config Drupal веб приложения, то я использую фичу автоматической трансформации applicationHost.config:

  1. Если в /site (на FTP, абсолютный путь будет d:\home\site) находиться файл applicationHost.xdt - Kudu будет пытаться трансформировать applicationHost.config вашего инстанса IIS для Azure web app
  2. Таким образом, я создал файл applicationHost.xdt через FTP со следующим контентом:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas..com/XML-Document-Transform">
<location path="%XDT_SITENAME%" xdt:Locator="Match(path)">
<system.webServer xdt:Transform="InsertIfMissing">
<security xdt:Transform="InsertIfMissing">
<ipSecurity allowUnlisted="false" denyAction="NotFound" xdt:Transform="InsertIfMissing">
<add ipAddress="1.1.1.1" allowed="true" />
</ipSecurity>
</security>
</system.webServer>
</location>
</configuration>

Данная заметка является компиляцией моего собственного опыта и следующих данных:

  • http://www.cptloadtest.com/2013/12/03/Git-And-Grunt-Deploy-To-Windows-Azure.aspx
  • https://blogs.msdn.microsoft.com/azureossds/2016/04/20/nodejs-and-npm-versions-on-azure-app-services/
  • https://github.com/projectkudu/kudu/issues/1787

Надеюсь, поможет кому-либо в будущем 🙂