1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vite+ と Alchemy を組み合わせたケースで 起こるGitHub Actions のデプロイエラー対処

1
Posted at

はじめに

先日、VoidZero から Vite+のAlpha版が発表された。Vite+とは、フロントエンドの各種ツールをワンセットにして管理しやすくした統合ツールチェーンである。

個人的にもうこれでいいだろって思ってしまうほどの良いツールなので、触ってない方はぜひ試してほしい。

試しに現在作成している個人開発アプリのプロジェクトに導入してみた。このプロジェクトでは GitHub Actions を利用して Cloudflare にデプロイするワークフローが組まれており、Vite+ の導入後に初めて CI/CD を回したところ、色々と面倒なエラーで詰まってしまった。

Vite+ のCIガイドを参考にしつつも解決せず、最終的に Vite+ のコマンド vp run と Alchemy の相性の悪さが原因だと分かった。

技術スタックは以下の通り。

  • フレームワーク: TanStack Start (React)
  • ビルドツール: Vite+ (vp)
  • IaC / デプロイ: Alchemy (alchemy deploy)
  • ホスティング: Cloudflare Workers

Alchemy は TypeScript で Cloudflare のリソース(Workers・R2・D1 など)を宣言的に管理する IaC ツールで、alchemy.run.ts にリソース定義を書いて alchemy deploy を実行するだけでインフラのプロビジョニングとデプロイが完結する。TanStack Start のような SSR フレームワークを Cloudflare Workers にデプロイするための TanStackStart ヘルパーも提供している。
https://alchemy.run/guides/cloudflare-tanstack-start/

第1のエラー:Command "vite" not found

エラー内容

GitHub Actionsのエラーログを確認すると以下の内容が流れていた。

Viteが見つからないらしい...

ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL  Command "vite" not found

Error: Command failed with exit code 254: pnpm vite build
    at async Website (alchemy/lib/cloudflare/website.js:139:9)
    at async Vite (alchemy/lib/cloudflare/vite/vite.js:38:12)
    at async TanStackStart (alchemy/lib/cloudflare/tanstack-start/tanstack-start.js:9:12)

▼ Deployステップにてpnpm alchemy deployで失敗している。

- name: Deploy
  run: pnpm alchemy deploy --stage ${{ env.STAGE }} --adopt 
  env:
    ALCHEMY_PASSWORD: ${{ secrets.ALCHEMY_PASSWORD }}
    ALCHEMY_STATE_TOKEN: ${{ secrets.ALCHEMY_STATE_TOKEN }}
    CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
    CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
    CLOUDFLARE_EMAIL: ${{ secrets.CLOUDFLARE_EMAIL }}

原因

Vite消失の原因は2つの事情が重なって起きていた。

① Vite+ への移行で node_modules/.bin/vite が消える

Vite+ に移行すると、package.json に以下が自動で設定される。

"devDependencies": {
    "vite": "npm:@voidzero-dev/vite-plus-core@latest"
},
"pnpm": {
    "overrides": {
        "vite": "npm:@voidzero-dev/vite-plus-core@latest"
    }
}

pnpm.overrides により、vite パッケージが @voidzero-dev/vite-plus-core に丸ごと差し替えられる。これは既存の Vite プラグインやフレームワークが vite という名前でパッケージを参照するため、プラグイン側を一切変更せずに Vite+ へ置き換えられるようにするための設計だ。

しかしこの差し替え後のパッケージは node_modules/.bin/vite というバイナリを登録しない。Vite+ の CLI は ~/.vite-plus/bin/vp としてグローバルにインストールされるものであり、node_modules/.bin には存在しない。

② Alchemy が pnpm vite build を自動生成して実行する

Alchemy には TanStack Start アプリを Cloudflare Workers にデプロイするための TanStackStart ヘルパーが用意されており、alchemy.run.ts でこのように使う。

// alchemy.run.ts
export const worker = await TanStackStart("website");

この TanStackStart はデプロイ時に内部でビルドコマンドを組み立てて実行する。プロジェクトのパッケージマネージャーを検出し、${runner} vite build の形でコマンドを構成する。

// alchemy/lib/cloudflare/vite/vite.js(抜粋)
const runner = await getPackageManagerRunner(); // → "pnpm"
build: spreadBuildProps(props, `${runner} vite build`),
// → "pnpm vite build" が実行される

① と ② が重なった結果pnpm vite buildnode_modules/.bin/vite を探しに行くが存在せず、Command "vite" not found になる。

対処

2か所を修正する。

ワークフロー
Vite+が提供する voidzero-dev/setup-vp@v1 を使う。
セットアップ後は ~/.vite-plus/binPATH に追加され、vp コマンドが使用可能になる。

# 変更前
- name: Setup pnpm
  uses: pnpm/action-setup@v4
  with:
      run_install: false
- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
      node-version: "24"
      cache: pnpm
- name: Install dependencies
  run: pnpm install

# 変更後
- name: Setup Vite+
  uses: voidzero-dev/setup-vp@v1
  with:
      node-version: "24"
      cache: true
- name: Install dependencies
  run: vp install

alchemy.run.ts:
Alchemy の TanStackStartbuild.command オプションでビルドコマンドを上書きできる。デフォルトの pnpm vite buildvp build に変更する。これにより、Command "vite" not foundを引き起こさなくなる。

// 変更前
export const worker = await TanStackStart("website");

// 変更後
export const worker = await TanStackStart("website", {
    build: { command: "vp build" },
});

第2のエラー:vp run と Alchemy の相性問題

CI ガイドに倣い、Workflowファイルのpnpm installvp install に、pnpm alchemy deployvp run deploy に変更したところ、次のエラーが出た。

エラー内容

failed to load config from vite.config.ts
[Vite+] resolve universal vite config error: Error: The Wrangler config path,
".../.alchemy/local/wrangler.jsonc", could not be found.
Please run `alchemy dev` or `alchemy deploy` to create it.
error: Failed to load task graph

原因

workflowsのDeploy ステップで vp run deploypackage.jsondeploy スクリプトを実行するコマンド)を使っていた。

deploy.yml
- name: Setup Vite+
  uses: voidzero-dev/setup-vp@v1
  with:
      node-version: "24"
      cache: true
- name: Install dependencies
  run: vp install
- name: Deploy
  run : vp run deploy
package.json
"build": "vp build",
"preview": "vp preview",     
"deploy": "alchemy deploy --stage $STAGE --adopt",            
"destroy": "alchemy destroy --stage $STAGE",                  

ここで問題が起きる。vp run はスクリプトを実行する前に vite.config.ts を読み込んでタスクグラフを構築する。この vite.config.ts 内には Alchemy の vite プラグインが含まれており、そのプラグインが .alchemy/local/wrangler.jsonc を要求する。

vite.config.ts
// vite.config.ts
import alchemy from "alchemy/cloudflare/tanstack-start";
import { defineConfig } from "vite-plus";

export default defineConfig({
    plugins: [
        alchemy(), // ← こいつが wrangler.jsonc を要求する
        // ...他のプラグイン
    ],
});

しかしwrangler.jsoncalchemy deploy を実行して初めて生成されるものだ。つまり

vp run deploy を実行
  → vite.config.ts を読む
    → Alchemy vite プラグインが wrangler.jsonc を要求
      → wrangler.jsonc は alchemy deploy が生成する
        → alchemy deploy はまだ実行されていない → エラー

鶏と卵の状態になっている。

vp run を使うことが根本的な相性問題

Vite+ のCI ガイドpnpm <script>vp run <script> に置き換える方針を示している。

# 公式ガイドの "After" 例
- run: vp install && vp run dev:setup
- run: vp check
- run: vp test

この方針は一般的なプロジェクトでは成立する。しかし Alchemy のように vite.config.ts に初期化時の副作用を持つプラグインを含む場合vp run 経由での実行は使えない。vp run が常に vite.config.ts を読むという仕様が仇になる。

対処

vp run を経由せず、node_modules/.bin/alchemy を直接呼ぶ。

alchemy deploy の実行順序は「Cloudflare リソースを作成 → wrangler.jsonc を生成 → vp build を呼ぶ」なので、vp buildvite.config.ts を読む時点では wrangler.jsonc がすでに存在する。直接呼び出しにすることで鶏と卵の問題が回避できる。

修正後のdeploy.yaml
- name: Deploy
  run: ./node_modules/.bin/alchemy deploy --stage ${{ env.STAGE }} --adopt

最終的なワークフロー

name: Deploy

on:
    push:
        branches:
            - main
            - dev

env:
    STAGE: ${{ github.ref_name == 'main' && 'prod' || github.ref_name }}

jobs:
    deploy:
        runs-on: ubuntu-latest
        permissions:
            contents: read
        steps:
            - uses: actions/checkout@v4
            - name: Setup Vite+
              uses: voidzero-dev/setup-vp@v1
              with:
                  node-version: "24"
                  cache: true
            - name: Install dependencies
              run: vp install
            - name: Deploy
              run: ./node_modules/.bin/alchemy deploy --stage ${{ env.STAGE }} --adopt
              env:
                  ALCHEMY_PASSWORD: ${{ secrets.ALCHEMY_PASSWORD }}
                  ALCHEMY_STATE_TOKEN: ${{ secrets.ALCHEMY_STATE_TOKEN }}
                  CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
                  CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
                  CLOUDFLARE_EMAIL: ${{ secrets.CLOUDFLARE_EMAIL }}

おわりに

まとめになるがvp run と Alchemy の組み合わせによって発生したエラーであった。

node_modules/.bin のバイナリを直接呼ぶことで回避できた。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?