Open6

Nxモノレポ上でAzure Functionsをビルド・デプロイできるようにするメモ

Nakano as a ServiceNakano as a Service

有志の人が以下のようなNxのインテグレーションを用意してくれていた
https://github.com/BeyerleinDigital/nx-azure-functions-integration

この記事も参考になる
https://blog.beyerleinf.de/azure-functions-esbuild

有志の人がesbuild-azure-functionsというnpmパッケージを作成してくれていた。これでesbuildに最適なオプションを渡せるらしい。

自分としてはひとまずシンプルに行きたいので、Nx上でesbuildが実行できればいい。
Nx公式のesbuild executorを使うことにした。
https://nx.dev/packages/esbuild/executors/esbuild

Nakano as a ServiceNakano as a Service

上の記事を参考にesbuildのビルドオプションをproject.jsonに追記する。最終的に以下のようになった。
関数が増えるごとに additionalEntryPoints を増やさなければならないが、仕方ないか。

    "build": {
      "executor": "@nrwl/esbuild:esbuild",
      "outputs": ["{options.outputPath}"],
      "options": {
        "bundle": true,
        "thirdParty": false,
        "format": ["cjs"],
        "platform": "node",
        "target": "node16",
        "skipTypeCheck": false,
        "outputPath": "apps/azfunc/dist",
        "additionalEntryPoints": [
         "apps/azfunc/HttpTrigger/index.ts"
        ],
        "main": "apps/azfunc/src/main.ts",
        "tsConfig": "apps/azfunc/tsconfig.app.json",
        "assets": ["apps/azfunc/src/assets"]
      },
      "configurations": {
        "production": {
          "minify": true,
          "sourcemap": false
        }
      }
    },

Nakano as a ServiceNakano as a Service

Azure Functionsは拡張子が .mjs のファイルをES Modulesのファイルとして認識し、それ以外はCommonJSと認識する。なので、生成されるファイルの拡張子を.mjsにしなければならないのだが、Nxのesbuild executorのソースコードを見ると、そのオプションが潰されてしまっている。何か理由があるのだろうか。

https://github.com/nrwl/nx/blob/ed159e865f48760e1d1d00af04c42ecfd07b5d29/packages/esbuild/src/executors/esbuild/lib/build-esbuild-options.ts#L34

まあES Modulesでなくてもいいやと思い、CommonJSでビルドすることにした。

Nakano as a ServiceNakano as a Service

Azure Functionsをローカルからデプロイするときには以下のコマンドを使った

func azure functionapp publish {functionsのリソースid}

だが、このコマンドを実行しても関数が生えてこない。このコマンドはカレントディレクトリのdistにあるビルド成果物を見に行くようだ。function.jsonscriptFileリポジトリルート/dist までの相対パスを書いてあげても意味がなかった。仕方がないので、apps/azfunc/dist にビルド成果物を吐くようにした。

Nakano as a ServiceNakano as a Service

GitHub ActionsでCIを組んだ。最終的なWorkflowは以下のようになった。
Azure Functionsのマネジメントコンソールから、GitHub CIの設定を行うと、テンプレートとなるWorkflowを勝手にコミットし、シークレットも設定してくれた。

ポイントは、モノレポのFunctionsのディレクトリまでcdして、esbuildによって生成されたpackage.jsonでnpm installしているところだ。こうすることで、カレントディレクトリに.node_modulesが生成され、デプロイのときにそれを含めてくれるようになる。

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: 'Checkout GitHub Action'
        uses: actions/checkout@v2

      - uses: pnpm/action-setup@v2
        with:
          version: 7
      - uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: pnpm

      - run: pnpm install --frozen-lockfile --ignore-scripts

      - run: pnpm exec nx build azfunc

      - run: |
          cp dist/package.json .
          npm install
        working-directory: apps/azfunc

      - name: 'Run Azure Functions Action'
        uses: Azure/functions-action@v1
        id: fa
        with:
          app-name: '{Functionsのリソース名}'
          slot-name: 'Production'
          package: apps/azfunc
          publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_XXXXXXXXXXXXXX }}
Nakano as a ServiceNakano as a Service

CIでのデプロイ前にローカルからfunc azureコマンドでデプロイをしたせいか、FunctionsのConfigulationにWEBSITE_RUN_FROM_PACKAGEという設定が追加されており、これによってCIが以下のようなエラーを吐いた。WEBSITE_RUN_FROM_PACKAGEを削除することで解決した。

 When request Azure resource at PublishContent, zipDepoy : WEBSITE_RUN_FROM_PACKAGE in your function app is set to an URL. Please remove WEBSITE_RUN_FROM_PACKAGE app setting from your function app.