miso_soup3 Blog

主に ASP.NET 関連について書いています。

日記 Xamarin.Forms 触った

日記です。

※1 Your Developer Program Membership has expired. Renew your membership to keep your access to Apple Developer Program benefits and services. Once renewed, be sure to agree to your Paid App Agreement in the Agreements, Tax and Banking section of iTunes Connect.

Custom Deployment for Azure Web Apps using CAKE

GitHub のソースから Azure WebApps にデプロイするときの Kudu カスタムデプロイ機能にて、
CAKE(C#) を使ったビルドを試してみました。

CAKE とは


http://cakebuild.net/

f:id:miso_soup3:20161228190401p:plain


C# のスクリプトでビルドのタスクを書くプロジェクトです。Roslyn と Mono で動くので、クロスプラットフォームなビルドシステムになります。
オープンソースです。
ググるときは、CakePHP がひっかかってしまうで、"CAKE build" "cakebuild" がいいです。(C# Make が由来っぽいけど…。)

↓このような感じで C# でビルドタスクを記述します。

f:id:miso_soup3:20161228181430p:plain

今回は、デプロイに加え、Web.config の置換をアドインでやってみました。ソースは、ASP.NET なプロジェクトを前提とします。

Sample : GitHub - hhyyg/CAKEWebAppCustomDeploy

試してみた手順

GitHub と Azure WebApps の連携

まず、GitHub のリポジトリ・Azure WebApps・ASP.NET なプロジェクトを用意します。
GitHub には、ASP.NET のプロジェクトを push しておきます。
次に、ポータルの Azure WebApps にて、「デプロイ オプション」を選択し、WebApps と GitHub を紐づけます。

f:id:miso_soup3:20161228181132p:plain

項目について:

似た項目が2つ「デプロイ オプション」と「継続的配信(プレビュー)」とありますが、
前者は Kudu が「MSBuild.exe」でビルドしますが、後者は、Visual Studio Team Service のビルドエージェントにてビルドを行います。
後者は Visual Studio Team Service にてビルドされますが、ソースは GitHub に置くことも可能です。

「継続的配信(プレビュー)」については、次の2つのドキュメントが参考になりました。

Visual Studio Team Servicesのサーバービルド機能を使う(8日目) - kkamegawa's weblog
Continuous delivery to Azure App Service from Release Management

Kudu のカスタムデプロイ

上記のように、GitHub と Azure WebApps を連携すると、すぐにデプロイが開始されます。
この仕組みについては、Azure Web App のカスタムデプロイを使って特定のディレクトリをGithubと同期する - tech.guitarrapc.cóm が参考になりました。

デプロイは、WebApps の「D:\home\site\deployments\tools」配下にある「deploy.cmd」が実行されます。

f:id:miso_soup3:20161228183153p:plain
(↑ https://{webappsの名前}.scm.azurewebsites.net/DebugConsole でアクセスできる Kudu の CMD 画面。)

カスタムデプロイを試す一歩として、GitHub リポジトリの root フォルダに「.deployment」ファイルを作成し、次のように記述します。

.deployment:

[config]
command = deploy.cmd

deploy.cmd は、先ほどの「D:\home\site\deployments\tools」配下からコピーし、GitHub リポジトリの root フォルダに配置します。

f:id:miso_soup3:20161228183512p:plain
(↑ GitHub リポジトリのフォルダ)

この状態で GitHub に push すると、deploy.cmd が実行されデプロイが行われます。
この「.deployment」ファイルや「deploy.cmd」等をカスタマイズすることが、いわゆる Kudu の カスタムデプロイと言われます。

カスタマイズ方法については:
Customizing deployments · projectkudu/kudu Wiki · GitHub
Configurable settings · projectkudu/kudu Wiki · GitHub

CAKE でビルドする

Kudu のカスタムデプロイ時に、CAKE でビルドを行うようにします。
Cake - Cake Kudu - Azure Web Deployment Addin こちらのサイトが参考になりました。が、そのままコピペするとエラーになります。
(余計なが入っていたり、\が/になっているため。)

先ほど作成した deploy.cmd ファイルを、次のように変更します。
deploy.cmd:

@echo off
IF NOT EXIST "Tools" (md "Tools")
IF NOT EXIST "Tools\Addins" (md "Tools\Addins")
nuget install Cake -ExcludeVersion -OutputDirectory "Tools"
Tools\Cake\Cake.exe deploy.cake -verbosity=Verbose

次に、同じく GitHub リポジトリの root フォルダに「deploy.cake」ファイルを作成し、次のように記述します。
deploy.cake:

#tool "KuduSync.NET" "https://www.nuget.org/api/v2/"
#addin "Cake.Kudu" "https://www.nuget.org/api/v2/"

///////////////////////////////////////////////////////////////////////////////
// ARGUMENTS
///////////////////////////////////////////////////////////////////////////////

var target          = Argument<string>("target", "Default");
var configuration   = Argument<string>("configuration", "Release");

///////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES
///////////////////////////////////////////////////////////////////////////////

var websitePath     = MakeAbsolute(Directory("./MisoDep"));
var solutionPath    = MakeAbsolute(File("./MisoDep.sln"));

if (!Kudu.IsRunningOnKudu)
{
    throw new Exception("Not running on Kudu");
}

var deploymentPath = Kudu.Deployment.Target;
if (!DirectoryExists(deploymentPath))
{
    throw new DirectoryNotFoundException(
        string.Format(
            "Deployment target directory not found {0}",
            deploymentPath
            )
        );
}

///////////////////////////////////////////////////////////////////////////////
// TASK DEFINITIONS
///////////////////////////////////////////////////////////////////////////////

Task("Clean")
    .Does(() =>
{
    //Clean up any binaries
    Information("Cleaning {0}", websitePath);
    CleanDirectories(websitePath + "/bin");
});

Task("Restore")
    .Does(() =>
{
    // Restore all NuGet packages.
    Information("Restoring {0}...", solutionPath);
    NuGetRestore(solutionPath);
});

Task("Build")
    .IsDependentOn("Clean")
    .IsDependentOn("Restore")
    .Does(() =>
{
    // Build all solutions.
    Information("Building {0}", solutionPath);
    MSBuild(solutionPath, settings =>
        settings.SetPlatformTarget(PlatformTarget.MSIL)
            .WithProperty("TreatWarningsAsErrors","true")
            .WithTarget("Build")
            .SetConfiguration(configuration));
});

Task("Publish")
    .IsDependentOn("Build")
    .Does(() =>
{
    Information("Deploying web from {0} to {1}", websitePath, deploymentPath);
    Kudu.Sync(websitePath);
});

Task("Default")
    .IsDependentOn("Publish");

///////////////////////////////////////////////////////////////////////////////
// EXECUTION
///////////////////////////////////////////////////////////////////////////////

RunTarget(target);

ここで、次の行を環境に合わせて編集します。

configuration の第二引数には、ビルドのモードを設定します。(Release など)
edit deploy.cake:

var target          = Argument<string>("target", "Default");
var configuration   = Argument<string>("configuration", "vsbuildrelease");

websitePath には、GitHub リポジトリ内の、発行対象となるフォルダを、
websitePath には、.sln ファイルパスを記述します。
edit deploy.cake:

var websitePath     = MakeAbsolute(Directory("./MisoDep"));
var solutionPath    = MakeAbsolute(File("./MisoDep.sln"));

以上のように編集した後、push を行うと CAKE によるビルドが走ると思います。
確認するには、Azure WebApps のポータルの「デプロイオプション」にてログを表示します。

f:id:miso_soup3:20161228184652p:plain

Web.config を変換する

このままでは、Web.config が適した Web.**.config へ変換されません。変換するには、GitHub - nengberg/cake-envxmltransform: A plugin for Cake for environment-based configuration transformations こちらのアドインを追加します。

ASP.NET のプロジェクトに第三のソリューション構成を作成して試してみます。

ビルド>構成マネージャー を開き、「vsbuildrelease」という名前で追加してみました。
f:id:miso_soup3:20161228184950p:plain
f:id:miso_soup3:20161228185050p:plain

Web.config が置換されたかどうか確認するために、構成ごとの appSettings の値をサイトに表示する、という手段をとります。

「Web.config」ファイルを右クリックし、「Config 変換を追加」をクリックします。「Web.vsbuildrelease.config」が追加されます。

「Web.config」ファイルにて、appSettings を追加します。

  <appSettings>
    <add key="Environment" value="Dev"/>

「Web.vsbuildrelease.config」には、次のように記述します。

  <appSettings>
    <add key="Environment" value="vsbuildrelease"
         xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>


ASP.NET のプロジェクト内にて、適当なページに次のように記述します。(例は Home.cshtml ファイルにて)

<div>
    Environment: @System.Configuration.ConfigurationManager.AppSettings["Environment"]
</div>

CALE ビルドを設定します。
3行目あたりに「#addin Cake.EnvXmlTransform」を追加します。
deploy.cake:

#tool "KuduSync.NET" "https://www.nuget.org/api/v2/"
#addin "Cake.Kudu" "https://www.nuget.org/api/v2/"
#addin Cake.EnvXmlTransform

deploy.cake L55 あたりに追加:

Task("Apply-Config-Transformations")
  .Does(() => {

    Information("Apply-Config-Transformations");
    var configFileFolder = "./*/*.config";
    var environment = configuration;
    ConfigTransform.ApplyTransformations(configFileFolder, environment);
});


64行目あたりで、次のように「.IsDependentOn("Apply-Config-Transformations")」を追加します。
deploy.cake L64:

Task("Build")
    .IsDependentOn("Clean")
    .IsDependentOn("Restore")
    .IsDependentOn("Apply-Config-Transformations")
    .Does(() =>
{
    // Build all solutions.
    Information("Building {0}", solutionPath);
    MSBuild(solutionPath, settings =>
        settings.SetPlatformTarget(PlatformTarget.MSIL)
            .WithProperty("TreatWarningsAsErrors","true")
            .WithTarget("Build")
            .SetConfiguration(configuration));
});

これでデプロイすると、Web.config が置換されてデプロイされるはずです。

ログを見ると次のように表示されました。
f:id:miso_soup3:20161228185704p:plain

CAKE のパッケージやアドインは、「D:\home\site\repository\Tools」配下にあります。

f:id:miso_soup3:20161228185831p:plain

その後、CAKE.Kudu 0.4.0 が更新され .NET Core に移行したみたいです。

また、こちら