自定义部署到 Azure 网站

Custom Deployment to Azure Websites

我最近开始使用 Gulp.js 将我所有的 CSS 和 JavaScript 打包成单个文件,然后将其包含在我的网络应用程序中。我的网络应用程序是用 Python 编写的(使用 Flask)。

我显然不想使用 git 跟踪 Gulp 输出 CSS 和 JS 文件(因为它们是构建输出文件)。

我使用推送部署将我的网站部署到 Azure 网站。也就是说,我只是 运行 git push azure master,Azure 会自动识别出我正在使用 Python、设置 virtualenv、安装 pip 依赖项等等。 This article describes how to set this up.

这个过程很有效,但现在我已经开始使用 Gulp,我想确保连接的 JavaScript 和 CSS 文件也在服务器端生成每当我部署网站时。

而且,以后我希望Azure 运行所有的测试都在部署时,全部通过才部署成功。

遗憾的是,我还没有为这个工作流程找到令人满意的解决方案,因为我无法将自定义步骤添加到 Azure 的自动部署过程中。

我曾尝试使用 Kudu (as suggested by this blog post) 编写自定义部署脚本,但这样做会禁用 Azure 通常执行的所有自动步骤; 运行ning azure site deploymentscript --python 只生成一个非常基本的 Kudu 部署文件,它不处理读取 web.config 文件、设置 virtualenv 或安装依赖项。我没有找到有关如何自己执行此操作的文档;我使用了默认的自动 Azure 部署脚本(当我推送代码时它会在服务器端生成,所以我自己无法访问它)因为否则不会处理诸如 virtualenv 和 pip 依赖项之类的东西。

是否有任何可用的解决方法,以便我可以自定义我的部署脚本(例如 运行 Gulp),同时仍能正确部署 Flask?

由于 Kudu 是开源的并且可以在 GitHub 上使用,我在它的问题跟踪器 (link, for anyone interested) 中提出了这个问题。代码所有者非常乐于助人,并向我指出了解决方案。

  1. 访问网站的 Kudu 服务:yourwebsite.scm.azurewebsites.net
  2. 单击“工具”>“下载部署脚本”并获取 Azure 为您的代码生成的部署脚本(这不仅限于 Flask 应用程序)。
  3. (可选)该脚本是一个 Windows 批处理脚本。我把它移植到 Bash,因为我更熟悉它,而且 Azure Websites 也支持它。
  4. 根据您的喜好添加自定义内容:使用 Gulp/Grunt、运行 测试构建内容并在部署失败时(以非零错误代码退出)等。您还应该记住首先检查是否使用 npm 和适当的 package.json 文件安装了 Gulp/Grunt 之类的东西。
    • 请注意,您应该只在 KuduSync 有机会从存储库复制新文件之前将部署标记为失败,否则它们最终会出现在您的 Web 根文件夹中,即使例如你的测试失败了。

这是我的代码处理片段 Gulp.js,供有兴趣的人使用。查看 azure site deploymentscript --node 生成的脚本以获取有关如何 select 正确的 Node 和 npm 版本的示例:

selectNodeVersion
echo "Invoking \"$NPM_CMD install\"..."
eval $NPM_CMD install
exitWithMessageOnError "Could not run 'npm install'.  Do you have the necessary privileges?"
echo "Finished npm install."

# The path doesn't seem to get set OK.  Use this hack to run gulp.
GULP="node_modules/gulp/bin/gulp.js"

echo "Running gulp..."
"$GULP" production
exitWithMessageOnError "Could not run 'gulp'.  Did 'npm install' run OK?"
echo "Finished gulp."

不要忘记实际添加一个包含所有必要 Gulp 依赖项的 package.json 文件到您的项目中。 Azure 提供 Node.js(和 npm)但不提供 Gulp.js。希望这对您有所帮助!

P.S.: 请注意,整个过程有点麻烦,完全正确的方法是使用持续集成代理。