理系学生日記

おまえはいつまで学生気分なのか

Serverless Frameworkのコマンド実行時にフックして他のコマンドを実行するserverless-scriptable-plugin

Serverless Frameworkの各種コマンド実行をフックし、任意の処理を挟み込む方法を紹介します。

背景

大量のLambda関数を管理するためにServerless Frameworkを利用しています。

ここで、問題が発生しました。 Prismaを利用したLambda関数をWindowsからデプロイしたLambda関数で、なぜかschema.prismaやPrisma Engineが見つからないという事象です。

ENOENT: no such file or directory, open '/var/task/schema.prisma'

課題

根本的な原因はわかっていないのですが、Lambda関数の配置されるディレクトリである/var/taskschema.prismaやPrisma Engineを配置すれば問題は解決します。 一方で、Prisma Engineたるlibquery_engine-rhel-*node_modules配下に配置されています。 Serverless FrameworkでLambda関数をデプロイする際、schema.prismaやPrisma Engineを同じディレクトリに移動せねばなりません。

つまり私が取り組むべき課題は、以下のように表現できます。

  • Windows OSからServerless Frameworkで「sls deploysls deploy functioinを実行するタイミング」で
  • schema.prismalibquery_engine-rhel-*をLambda関数と同一ディレクトリに移動したい

serverless-scriptable-plugin

上述の課題解決を可能にするのがserverless-scriptable-pluginというServerless FrameworkのPluginです。

この手のPluginには、他にserverless-hooks-pluginやserverless-plugin-scriptsがありますが、試行してみると上記プラグインが一番使い勝手が良かったです。

設定は以下のような形で、Serverless Frameworkの設定ファイルであるserverless.ymlに記述します。

plugins:
  - serverless-scriptable-plugin

custom:
  scriptable:
    hooks:
      before:package:initialize: npm run hook:copy
      before:deploy:function:initialize: npm run hook:copy
      before:deploy:deploy: npm run hook:copy

上記でわかるように、任意のnpm scriptsを挟み込めます。どんなフックが用意されているのかは以下のGistを参考にしました。

npm script

Windows OSとその他OSでnpm scriptを切り替えるのは、[run-script-os]と[npm-run-all]の組み合わせで実現できます。 このあたりは以下の記事がいい感じでカバーしてくれるので、ご一読いただければと。

npm scriptsは以下になりました。

    "hook:copy": "run-script-os",
    "hook:copy:nix": "cp prisma/schema.prisma node_modules/.prisma/client/libquery_engine-rhel-* ./; ",
    "hook:copy:windows": "run-p hook:copy:windows:*",
    "hook:copy:windows:schema": "copy /y prisma\\schema.prisma .\\",
    "hook:copy:windows:engine": "copy /y node_modules\\.prisma\\client\\libquery_engine-rhel-* .\\"