🔖

HonoでRPCをしたAzureStaticWebAppsをAzureDevOpsのパイプラインからデプロイしたメモ

2024/07/31に公開

概要

前回はCRUDを作成した。
ここまではswa経由でデプロイしていたが、パイプライン経由でデプロイできるようにする。
パイプライン上でビルドするにあたって問題がおこり、追加の設定が必要になったのでメモしておく。

ソースコード

パイプライン

.azure-devops/app-deploy-pipelines.yaml
trigger:
  branches:
    include:
      - develop
  paths:
    include:
      - apps/pl-app/*
      - .azure-devops/app-deploy-pipelines.yaml
pool:
  vmImage: ubuntu-latest
steps:
  - task: AzureStaticWebApp@0
    name: DeployStaticWebApp
    displayName: Deploy Static Web App
    inputs:
      config_file_location: /apps/pl-app
      output_location: /apps/pl-app/dist
    env:
      azure_static_web_apps_api_token: $(deployment_token)
      CI: true

パイプラインのVariablesdeployment_tokenにはswaからのデプロイでも使用していたデプロイトークンを設定する。

問題1: ビルドに使用するAzureDevOpsのパイプラインのNodeが古い

発生したエラー

Node Build Command Manifest file created.

Using Node version:
v16.20.2

Using Npm version:
8.19.4

Running 'npm install'...

npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'glob@11.0.0',
npm WARN EBADENGINE   required: { node: '20 || >=22' },
npm WARN EBADENGINE   current: { node: 'v16.20.2', npm: '8.19.4' }
npm WARN EBADENGINE }

対処法

Azure Static Web Apps でサポートされている言語とランタイムより、package.jsonでengineを指定。

package.json
{
  "name": "async-ttrpg",
  "version": "0.0.0",
  "description": "sakutto trpg",
  "scripts": {
    "prepare": "husky",
    "ncu": "turbo ncu",
    "build": "turbo build",
    "dev": "turbo dev"
  },
  "author": "hibohiboo",
  "license": "MIT",
  "devDependencies": {
    "husky": "^9.1.4",
    "npm-check-updates": "^16.14.20",
    "prettier": "^3.3.3",
    "turbo": "^2.0.10"
  },
  "packageManager": "npm@10.8.2",
  "private": true,
  "workspaces": [
    "packages/*",
    "apps/*"
  ],
+  "engines": {
+    "node": ">=20.15.1"
+  }
}

問題2: huskyが見つからずにエラー

発生したエラー

Using Node version:
v20.15.1

Using Npm version:
10.7.0

Running 'npm install'...


> async-ttrpg@0.0.0 prepare
> husky

sh: 1: husky: not found
npm error code 127
npm error path /working_dir
npm error command failed
npm error command sh -c husky

npm error A complete log of this run can be found in: /root/.npm/_logs/2024-07-30T14_44_05_534Z-debug-0.log


---End of Oryx build logs---
Oryx has failed to build the solution.

対処法

パイプライン上ではgitのチェックなどは不要なので、skipping-git-hooksを参考に、パイプライン上では動作させないようにした。

{
  "name": "async-ttrpg",
  "version": "0.0.0",
  "description": "sakutto trpg",
  "scripts": {
-    "prepare": "husky",
+    "prepare": "node .husky/install.mjs",
    "ncu": "turbo ncu",
    "build": "turbo build",
    "dev": "turbo dev"
  },
  "author": "hibohiboo",
  "license": "MIT",
  "devDependencies": {
    "husky": "^9.1.4",
    "npm-check-updates": "^16.14.20",
    "prettier": "^3.3.3",
    "turbo": "^2.0.10"
  },
  "packageManager": "npm@10.8.2",
  "private": true,
  "workspaces": [
    "packages/*",
    "apps/*"
  ],
  "engines": {
    "node": ">=20.15.1"
  }
}
.husky/install.mjs
if (process.env.NODE_ENV === 'production' || process.env.CI === 'true') {
  process.exit(0)
}
const husky = (await import('husky')).default
console.log(husky())

問題3: 依存関係によるエラー

発生したエラー

@async-ttrpg/pl-app:build: > @async-ttrpg/pl-app@0.0.0 build
@async-ttrpg/pl-app:build: > tsc -b && vite build
@async-ttrpg/pl-app:build: 
@async-ttrpg/api:build: 
@async-ttrpg/api:build: > @async-ttrpg/api@0.0.0 clean
@async-ttrpg/api:build: > rimraf dist
@async-ttrpg/api:build: 
@async-ttrpg/api:build: 
@async-ttrpg/api:build: > @async-ttrpg/api@0.0.0 build
@async-ttrpg/api:build: > tsc && tsc-alias && cp -r generated/client dist/generated/client
@async-ttrpg/api:build: 
@async-ttrpg/pl-app:build: ../api/src/shared/prisma.ts(1,30): error TS2307: Cannot find module '@db/client' or its corresponding type declarations.
@async-ttrpg/pl-app:build: ../api/generated/zod/index.ts(2,29): error TS2307: Cannot find module '@db/client' or its corresponding type declarations.
@async-ttrpg/pl-app:build: src/characters/List.tsx(14,41): error TS7006: Parameter 'y' implicitly has an 'any' type.
@async-ttrpg/pl-app:build: npm error Lifecycle script `build` failed with error:
@async-ttrpg/pl-app:build: npm error Error: command failed
@async-ttrpg/pl-app:build: npm error   in workspace: @async-ttrpg/pl-app@0.0.0
@async-ttrpg/pl-app:build: npm error   at location: /working_dir/apps/pl-app
@async-ttrpg/pl-app:build: ERROR: command finished with error: command (/working_dir/apps/pl-app) /opt/nodejs/20.15.1/bin/npm run build exited (1)
@async-ttrpg/pl-app#build: command (/working_dir/apps/pl-app) /opt/nodejs/20.15.1/bin/npm run build exited (1)

 Tasks:    0 successful, 3 total
Cached:    0 cached, 3 total
  Time:    15.463s 
Failed:    @async-ttrpg/pl-app#build

 ERROR  run failed: command  exited (1)


---End of Oryx build logs---
Oryx has failed to build the solution.

対処法

1. ファイルが足りないことの解決

ローカルではclientは既に作成済だったので気にしていなかった。
ビルド前にちゃんとgenerateするように設定

apps/api/package.json
{
  "name": "@async-ttrpg/api",
  "version": "0.0.0",
  "description": "",
  "scripts": {
-    "prebuild": "npm run clean",
+    "prebuild": "npm run clean && npm run prisma-generate",
    "build": "tsc && tsc-alias && cp -r generated/client dist/generated/client",
    "watch": "tsc -w",
    "clean": "rimraf dist",
    "predev": "npm run build",
    "dev": "func start --port 7071",
    "lint": "eslint",
    "prisma-pull": "prisma db pull",
    "prisma-generate": "prisma generate",
    "deploy": "dotenv -e .env -- bash -c 'bash deploy.sh'"
  },
  "dependencies": {
    "@azure/functions": "^4.5.0",
    "@hono/swagger-ui": "^0.4.0",
    "@hono/zod-openapi": "^0.15.1",
    "@marplex/hono-azurefunc-adapter": "^1.0.0",
    "@prisma/client": "^5.17.0",
    "date-fns": "^3.6.0",
    "hono": "^4.5.1",
    "mssql": "^11.0.1",
    "zod": "^3.23.8"
  },
  "devDependencies": {
    "@async-ttrpg/eslint-config-custom": "*",
    "@async-ttrpg/tsconfig": "*",
    "@types/mssql": "^9.1.5",
    "@types/node": "^20.14.12",
    "dotenv-cli": "^7.4.2",
    "prisma": "^5.17.0",
    "rimraf": "^6.0.1",
    "tsc-alias": "^1.8.10",
    "typescript": "^5.5.4",
    "zod-prisma-types": "^3.1.8"
  },
  "optionalDependencies": {
    "@rollup/rollup-linux-x64-gnu": "^4.19.1"
  },
  "main": "dist/src/{app.js,functions/*.js}"
}

2.依存関係の明示

ログをみると、フロントエンドのビルド(@async-ttrpg/pl-app:build: > tsc -b && vite build)がバックエンドのビルドより先に走っている。
これではgenerateが間に合わないので順序関係を明示してあげる。(参考:turborepo)

turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": [".env"],
  "tasks": {
    "ncu": {},
    "dev": {},
    "prebuild": {},
    "build": {
      "outputs": ["dist"]
     },
+     "@async-ttrpg/pl-app#build": {
+      "dependsOn": ["@async-ttrpg/api#build"]
+     }
  }
}

問題4: viteのエラー

発生したエラー

@async-ttrpg/pl-app:build: /working_dir/node_modules/rollup/dist/native.js:59
@async-ttrpg/pl-app:build: 		throw new Error(
@async-ttrpg/pl-app:build: 		      ^
@async-ttrpg/pl-app:build: 
@async-ttrpg/pl-app:build: Error: Cannot find module @rollup/rollup-linux-x64-gnu. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try `npm i` again after removing both package-lock.json and node_modules directory.
@async-ttrpg/pl-app:build:     at requireWithFriendlyError (/working_dir/node_modules/rollup/dist/native.js:59:9)
@async-ttrpg/pl-app:build:     at Object.<anonymous> (/working_dir/node_modules/rollup/dist/native.js:68:76)
@async-ttrpg/pl-app:build:     ... 3 lines matching cause stack trace ...

対処法

cd apps/pl-app && npm i --save-optional @rollup/rollup-linux-x64-gnu
apps/pl-app/package.json
{
  "name": "@async-ttrpg/api",
  "version": "0.0.0",
  "description": "",
  "scripts": {
    "prebuild": "npm run clean && npm run prisma-generate",
    "build": "tsc && tsc-alias && cp -r generated/client dist/generated/client",
    "watch": "tsc -w",
    "clean": "rimraf dist",
    "predev": "npm run build",
    "dev": "func start --port 7071",
    "lint": "eslint",
    "prisma-pull": "prisma db pull",
    "prisma-generate": "prisma generate",
    "deploy": "dotenv -e .env -- bash -c 'bash deploy.sh'"
  },
  "dependencies": {
    "@azure/functions": "^4.5.0",
    "@hono/swagger-ui": "^0.4.0",
    "@hono/zod-openapi": "^0.15.1",
    "@marplex/hono-azurefunc-adapter": "^1.0.0",
    "@prisma/client": "^5.17.0",
    "date-fns": "^3.6.0",
    "hono": "^4.5.1",
    "mssql": "^11.0.1",
    "zod": "^3.23.8"
  },
  "devDependencies": {
    "@async-ttrpg/eslint-config-custom": "*",
    "@async-ttrpg/tsconfig": "*",
    "@types/mssql": "^9.1.5",
    "@types/node": "^20.14.12",
    "dotenv-cli": "^7.4.2",
    "prisma": "^5.17.0",
    "rimraf": "^6.0.1",
    "tsc-alias": "^1.8.10",
    "typescript": "^5.5.4",
    "zod-prisma-types": "^3.1.8"
  },
+  "optionalDependencies": {
+    "@rollup/rollup-linux-x64-gnu": "^4.19.1"
+  },
  "main": "dist/src/{app.js,functions/*.js}"
}

Vite のビルド時に出た Cannot find module @rollup/rollup-linux-x64-gnu. の解決より引用。

Viteのプロダクションビルドでは、Rollupを使ってビルドが行なわれている。
このRollupでのビルドには、rollupパッケージの代わりに、事前にコンパイルされたバイナリファイルが使用される。
そのためビルドする際には、ビルド環境に合わせてコンパイルされたバイナリファイルが必要となる。

Discussion