BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

GitHub Actions で ASP.NET MVC ( .NET Framework 4.8 ) を Azure App Service (Web App) へデプロイ

ASP.NET MVC ( .NET Framework 4.8 ) のアプリを GitHub Actions での CI/CD して Azure の App Service (Web Apps) へのデプロイするまでの方法を書いていきます。

ここら辺のドキュメントとか情報は少ないのが書こうと思ったモチベーションでした...と思って下書きして数か月放置してして今に至ります。

序盤はビギナー向けに GitHub の UI で初めて YAML を書くときの流れや Tips をダラダラ書いています。
ビギナーじゃない方には、後半のセクション: YAML のコード全体 もおいてるのでそれだけ見ればいい感もあります。

準備: ASP.NET Web アプリケーション (.NET Framework) のプロジェクト作成

今回は ASP.NET MVC (.NET Framework) のアプリの CI/CD の話なので、VS 2022 で ASP.NET Web アプリケーション (.NET Framework) を選びます。ここら辺は説明雑に進めます。

今回は MVC のテンプレートを選びましたが、Web API や空のやつでもシンプルに C# /Razor だけでコード書くなら一緒だと思います。SPA はビルド時に色々あるのかなとかだし Web Form は使う気がないので試す気はないので、この二つは対象外。

プロジェクトができてフォルダーを見たら .gitignore のファイルが無かったので、.sln ファイルがあるフォルダで以下のコマンドで作成しました。

dotnet new gitignore

ちなみにルートのフォルダはこんな感じ。ルートに sln ファイルがあります。csproj のパスは .\AspnetMvc48\AspnetMvc48.csproj です。

あとは GitHub 上でやろうと思うので、GitHub の repo に push しちゃいます (ローカル環境で YAML 書いても別に一緒ですが) 。

GitHub Actions の作成

今回は入門向けに GitHub Actions の UI 上で workflow を作る方法で進めます。

慣れてくると GitHub Actions で実際に使う Action が公開されている repo の README を確認しながらやった方が早いかもです。

YAML ファイルの追加

GitHub でプロジェクトを置いた repo を開き Actions タブをクリックします。GitHub Actions の workflow が存在しない場合はこんな画面になるので、set up a workflow yourself をクリックします。

既になんらかの workflow がある場合は New workflow ってボタンをクリックすると上の画面に行きます。

これで、ファイルができるので、まずは画面上部にファイル名が入力できます。わかりやすい名前をつけてあげましょう。ここでは aspnet-netframework-cicd.yml としました。

あとは name と以下のコードを書きます。

name: ASP.NET MVC (.NET Framework 4.8) to App Service

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
  workflow_dispatch:

jobs:
  build:
    runs-on: windows-latest

    steps:
      - uses: actions/checkout@v3

先頭の name は Actions タブを開いた際にこんな感じで見えます。後ろの文字までは見えないので、その点を考慮して UI 上で判別しやすい名前を付けてあげましょう。

あとは on とか最初の actions/checkout は毎度のことなので説明は省きます。バージョンはちょいちょいアップデートがあるのでドキュメント見ながら進めましょう。

msbuild のセットアップ

.NET Framework のビルドには MSBuild を使うのでそれを入れます。使うアクションは以下です。

何使えばわからないときの探し方として、まずは右側の Marketplace の検索で「msbuild」と入れればなんか出てくることがほとんどなので、検索しましょう。

microsoft が作った setup-msbuild がでるのでクリックするとこんな画面になります。Version を選んでコピーボタンクリックして貼り付けてながらコメントみるのもよいですし、View full Marketplace listing をクリックすると使い方の説明が書いてあることが多いのでそこのコードをはるのもよいです。

今回はシンプルにこれだけを追加します。

      - name: Add msbuild to PATH
        uses: microsoft/setup-msbuild@v1.1

NuGet のセットアップと NuGet パッケージの復元

NuGet をセットアップして Restore する

まずは NuGet の復元を NuGet CLI で行う方法を書きます。前述同様に検索したりして見つけて使いましょう。

setup と restore で追加するコードはこちら。今回はルートに AspnetMvc48.sln がある前提で nuget restore をしていますが、そうでない場合はただしいパスを指定しましょう。

      - name: Setup NuGet
        uses: nuget/setup-nuget@v1

      - name: Restore NuGet packages
        run: nuget restore AspnetMvc48.sln

msbuild のオプションで復元も可能

この方法は諸条件が必要だったりするのでドキュメントのリンクだけにします。

ビルド

msbuild の実行

後は msbuild コマンドでビルドを実行するだけです。

今回は .sln ファイルのパスは .\AspnetMvc48.sln なのでそのファイルを指定します。

     - name: Build
        run: msbuild AspnetMvc48.sln /p:Configuration=Release /p:DeployOnBuild=true /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:publishUrl=${{ github.workspace }}\publish /p:PrecompileBeforePublish=true /p:EnableUpdateable=false

色々とオプションがついていますが、これは Azure の App Service (Web App) に最適なデプロイオプションだと思ってください。詳しい話はしばやんのブログが一番わかりやすいです。公式ドキュメントでは探しにくいです。

Azure Pipelines から Run From Package としてデプロイする - しばやん雑記

その他参考になるドキュメントとして、直接的なプロパティのドキュメントではないし .NET Core のドキュメントなので msbuild の話から多少それるんですが、以下のドキュメント書かれてるプロパティの項目・使い方は参考にしてます。

ASP.NET Core アプリを配置するための Visual Studio 発行プロファイル (.pubxml) | Microsoft Learn

より実践的な話として、このジョブ内で単体テストや .editorconfig を使ったフォーマットのチェックなど、p実行したいところですが、本質からはずれるのでここでは書いてません。

ポイント1 : プリコンパイルのオプション

ASPNET MVC の プリコンパイル をするオプションである /p:PrecompileBeforePublish=true は、プロジェクトの構成によっては仕様上エラーでできないこともあるので、エラーになる際は外しましょう。

ポイント 2: ビルド成果物 (build artifact) の出力パスの指定

ここでは build artidact は /p:publishUrl=${{ github.workspace }}\publish と指定しました。GitHub Actions の github context を使っています。

相対パスで書いても全然 OK です。
ただ、より複雑なワークフローを作ってると workind-directory を使ったりコマンド内でパスを変更することがあると出力のパスが変わって後続の処理で影響が出るケースもことがある `${{ github.workspace }}`` を明示的に書いています。

(と、私がむかーしはまったので、個人的にはこういう策をとっています)

ポイント 3: GitHub Actions の msbuild の実行ログ

GitHub Actions で msbuild 実行時にログに大量に出てよくわからんとかログをもっと出したいとかは、ログのレベルを変えることで見やすくできます。以下ドキュメントリンクで -verbosity:level と書かれている部分に設定できるオプションの記載があります。省略形だと -v:m とか -v:diag とかで指定します。エラーの解析時にあまりにエラーが多いときは m (minimal) だと比較的エラーのみをすっきり出してくれます。

ポイント 4: コマンドの実行はまずローカルで試そう

msbuild のコマンドのエラーがでると GitHub Actions 上で調査は生産性が低いので、まずは実行したいコマンドをローカル PC で実行して動くことを試しましょう。その際、先述の github コンテキストを使ったパスの指定は自分の PCのパスや相対パスに直す必要があります。

Artifact のアップロード

GitHub Actions では、ジョブ間でファイルを共有する場合、専用のストアへアップロードする必要があります。
ジョブ自体は基本的に個別に動いているため、特定のジョブでファイルを GitHub Actions のホストに置いたからといって別のジョブではそのファイルは存在しないのです。

アップロードは actions/upload-artifact を使うだけで簡単です。

name は適当ですが、アップロードするファイルのパスはビルド時に指定した場所になります。これでこのジョブは完了です。

      - name: Upload Artifact
        uses: actions/upload-artifact@v3
        with:
          name: app
          path: ${{ github.workspace }}\app.zip

Artifact のデプロイと App Service へのデプロイ

前のジョブでアップロードした build artifact をダウンロードするのは actions/download-artifact を使ってサクッとできます。

App Service へのデプロイは azure/webapps-deploy を使っているだけなのでここでは詳しく書きませんが azure/webapps-deploy の README みれば。

 deploy:
    needs: build
    runs-on: windows-latest
    steps:
      - name: Download app
        uses: actions/download-artifact@v3
        with:
          name: app
          
      - name: Deploy to App Service
        uses: azure/webapps-deploy@v2
        with: 
          app-name: "app-eru-netframework-mvc"
          publish-profile: ${{ secrets.AZURE_APP_SERVICE_PUBLISH_PROFILE }}
          package: ${{ github.workspace }}\app.zip

補足な余談として、Azure へのログインはこれでやるのが現時点のベストな方法です。

blog.beachside.dev

YAML のコード全体

作るための手順を長々と書きましたが、できたものはこちら。

利用している action のバージョンはこのブログ書いてる時点の最新版なので、未来でこれを参考にする際は最新のバージョンを確認しながら構成していきましょうね。

まとめ

.NET Core にしたらもうちょっとしゅっとできて平和になります。