author: GeneralD
Claude Code スキルを作って、5つつまずいた話

Astro + Cloudflare Workers でを
する Claude Code
——
launch-site——をました。
終えてみると、5つの
を踏んでいました。
に
いない
、
の
、「それ
ですか」という
。
で
た
に
ます。
1つめ: Workers Builds にトリガー API はない
最初、こうていました——Workers Builds の
を REST API で
、
push 後にが
する、と。
Cloudflare の API リファレンスをました。
ませんでした。GitHub Actions
ならあります。
には「Connect to Git」
があります。でも「
を
する」REST
は
しません。
flowchart LR
A["期待\nPOST /workers/builds/trigger"] -->|そんな API ない| B["404"]
C["実際の仕組み"] --> D["Git push を検知"]
D --> E["Cloudflare が自動でビルド"]
C --> F["ダッシュボードで手動トリガー\n(UI のみ)"]
Workers Builds は「push で」という
で
ていて、
から
を
を
に
いないようです。
回避策は **git push をとして
**ことでした。
は Astro
を
して
する。
は Cloudflare が
。それ以上の
は
ました——というか、
ませんでした。API が
と
時点で
を
たので、むしろ
になりました。
2つめ: headless Chromium は Cloudflare ダッシュボードに弾かれる
Workers Builds をには、まず Git
との
を
で
しなければなりません。
に「
を
させよう」と
playwright-cli を
しました。
dash.cloudflare.com にしたら、こうなりました。
Just a moment...
Performing security verification...
Cloudflareが、headless Chromium の
を
ました。
で
の
が
を噴く——なかなか
です。
headlessを
て
--headed でしても、
がなければ
で
ます。
突破口は browser session transplant——使い
から
を
です。
を
してから
--headed でしたら、
を
して
済みの
に
しました。
の
はこうです。既存
の
を
storageState として、次回
時に
。
# ブラウザの cookie を storageState として書き出す
~/.config/bin/pw-import-session --browser arc \
--domain dash.cloudflare.com --domain .cloudflare.com \
--out "${XDG_STATE_HOME:-$HOME/.local/state}/playwright-cli/state/cloudflare.json" \
--load-session cloudflare
// Playwright 起動時に storageState を読み込む
const context = await browser.newContext({
storageState: `${process.env.XDG_STATE_HOME ?? `${process.env.HOME}/.local/state`}/playwright-cli/state/cloudflare.json`,
});
一度を
、どの
にも
ます。
まわりは「
で一度きちんと
」と、あとが
になります。
3つめ: bunx wrangler がファントムバージョンを引く
Wrangler は Cloudflare Workers の CLI です。
は
bunx wrangler deploy をいました。これが
の
を
ました。
$ bunx wrangler --version
⛅️ wrangler 4.14.0 ...
は 4.14.0。でも実際に
いたのは
の
node_modules/.bin/wrangler ではなく、bunx がに
した別
でした。
package.json に
"wrangler": "^3.x" をして、
bunx がから 4.x を
きます。
bunx は npx の Bunで、
package.json のに
ません。
に
済みの
を優先するはずですが、
によっては
node_modules/.bin/wrangler すらします。
は
で、**
node_modules/.bin/wrangler を直接**か、
bun run で package.json の scriptsにします。
# NG: ファントムバージョンを引く可能性がある
bunx wrangler deploy
# OK: package.json に固定したバージョンが確実に動く
./node_modules/.bin/wrangler deploy
あるいは wrangler を devDependencies にして
bun install を必ず先に。
bunx の「さ」に
と、
が
ます。
で
時に
が
いると、
するまで
がかかります。
4つめ: playwright-cli の三か所
Playwright でを
始めたら、三か所で
ました。
した
なので一つずつ
ます。
ひとつ: goto の戻りタイミング
page.goto(url) は load後に resolve します。SPA は
load が来ても JS のが
いません。
の「Git に
」
が DOM に
前に次の
へ
、
が
ず
。
// NG: ボタンが DOM に現れる前に進んでしまう
await page.goto('https://dash.cloudflare.com/...');
await page.click('[data-testid="connect-git"]');
// OK: 目標要素の出現を待つ
await page.goto('https://dash.cloudflare.com/...');
await page.waitForSelector('[data-testid="connect-git"]', { state: 'visible' });
await page.click('[data-testid="connect-git"]');
waitForSelector での
を
。これだけです。
goto のを「
」と
ことが
です。
ふたつ: SPA のナビゲーションタイムアウト
の途中、Cloudflare が GitHub OAuth に
します。OAuth
後に Cloudflare
に
まで、
waitForNavigation がデフォルト 30で
ました。
timeout を 120まで
て
しました。OAuth の
は
の
が
な場合もあるので、
は「
の
」を
にしました。
は
を持って
したほうが
です。
みっつ: window.confirm が自動キャンセルされる
GitHubの最後、「本当に
しますか」
が
window.confirm で出ます。Playwright はでネイティブ
を自動 dismiss します——つまり「キャンセル」を
。
// ダイアログを自動承認する
page.on('dialog', async (dialog) => {
await dialog.accept();
});
これをないと、
したつもりが永遠に
されます。
dialog イベントのハンドラは、が
な
では
——そう
づけました。
5つめ: Git アカウントセレクターのサイレント失敗
GitHubで「どの
で
するか」を
があります。
は
で
を
しようとしました。
問題は、しただけでは
されないことです。

で
を
→ 「次へ」 → 次の
へ
。ここまでは
ます。しかし「次へ」の内部で
の
が
おり、その
前に進むと
が
null のまま後続の API がます。
には何も
。
もありません。ただ
null でます。
page.waitForResponse でネットワークの
を
ことで
しました。
// アカウント選択後、保存 API のレスポンスを待つ
const [response] = await Promise.all([
page.waitForResponse((resp) =>
resp.url().includes('/api/accounts') && resp.status() === 200
),
page.selectOption('#account-selector', orgAccountId),
]);
に何も
まま
が
は、
で
のに一番
がかかりました。「
のに
」を
、まず
を
——これが
で
ことです。
やってみて分かったこと
5つ、5つ
ました。
を
とき、「API がある
」で
しないほうが
です。Workers Builds のように、
に API が
もあります。
push = と
と、
はむしろ
になりました。
は、「
」を
。
goto のは
の
ではなく、
は
がなければ
、
は
で
。
は
に
して
に
ます。
みて
のは、
と、どこが
いるのかが
で分かる——という一点でした。