Skip to content

ci(repo): deploy の PR コメント経路と permissions を締め、Playwright キャッシュと e2e のポート伝播を足す (#239 #198) - #265

Merged
shinyaoguri merged 2 commits into
mainfrom
ci/p3-deploy-hardening-and-e2e-ports
Aug 15, 2026
Merged

ci(repo): deploy の PR コメント経路と permissions を締め、Playwright キャッシュと e2e のポート伝播を足す (#239 #198)#265
shinyaoguri merged 2 commits into
mainfrom
ci/p3-deploy-hardening-and-e2e-ports

Conversation

@shinyaoguri

@shinyaoguri shinyaoguri commented Aug 15, 2026

Copy link
Copy Markdown
Owner

目的

2026-08 レビュー (#243) の残件のうち CI / e2e の低コスト指摘 2 件。

PR #254 との重複はありません。 #254pr-title.yml / freshness.yml の新規追加と .claude/settings.json / CHANGELOG / ADR が対象で、deploy.yml には一切触れていません。

⚠️ #239 子項目① は Issue の前提が誤りだったことが CI の実測で判明したため、当初の修正を取り下げました。 詳細は下記。

#239 — CI の磨き込み (3 子項目)

子項目 着手前 本 PR の結論
① PR プレビューの文字列直展開 未解決とされていた command: は非該当 (Issue の前提が誤り) / command-output実在したので修正
② top-level permissions 実効は解消・YAML は未宣言 明示を追加
③ Playwright キャッシュ 未解決 (リポジトリ全体に actions/cache が 0 件) 追加

①-a command: — Issue の前提が誤りだった (修正を取り下げ)

当初 github.head_ref などを env: 経由のシェル変数参照に変えましたが、CI で deploy-preview が落ちて前提の誤りが判明しました

[command] npx wrangler pages deploy ./dist --project-name=$CF_PROJECT_NAME --branch=$PREVIEW_BRANCH ...
✘ [ERROR] The Pages project "$CF_PROJECT_NAME" does not exist.

wrangler-action v4 は command: をシェルに渡さず、トークン分割して npx を直接 exec します。 よって:

  • $VAR は展開されない → env 経由の「修正」はデプロイを壊す
  • シェルが介在しない以上、head_ref に含まれうる ; $ & バッククォートは不活性
  • git はブランチ名に空白を許さないため、引数分割も起きない

つまり command: にコマンドインジェクションは成立しません。直接展開のまま戻し、次に読む人が同じ「修正」を当てて再びデプロイを壊さないよう、実測の根拠をコメントで残しました

事前に wrangler-actionsrc/exec.ts を読んで「child_process.exec() = シェル経由」と判断したのが誤りで、command: 入力はその経路を通っていませんでした。CI が実物で反証してくれた形です。

① -b command-output — こちらは実在したので修正

actions/github-scriptscript:本物の JS 評価なので、こちらは実在の問題です。

const output = `${{ steps.preview-deploy.outputs.command-output }}`;

wrangler の出力にバッククォートや ${ が混ざった瞬間にスクリプトごと壊れて job が落ちますenv: 経由で渡し process.env 参照に変更しました。以降の output.match(...) 以下のロジックは無変更です。

② top-level permissions

contents: read を明示。実効の変化はありません (リポ設定側で default_workflow_permissions: read)。目的は明示性と、将来リポ設定が変わったときの防御です。labeler.yml / pr-title.yml / freshness.yml は既に top-level 宣言を持っており、deploy.yml だけが取り残されていました。job level の 3 箇所は据え置き。

③ Playwright キャッシュ

~/.cache/ms-playwright をキャッシュ。キーには npx playwright --version が報告する実解決バージョンを使っています (package-lock.json のハッシュだけだと Playwright と無関係な依存更新でも無効化されるため)。--with-deps が入れる OS パッケージはキャッシュ対象外なので、npx playwright install 自体はヒット時も実行したままです。

#198 — e2e にポートが渡っていない

webServerport: EDITOR_PORT / port: WORKERS_PORT を宣言しているのに、起動コマンドにはポートが一切渡っていません (env:--port も無し)。結果:

  • E2E_EDITOR_PORT を指定しても実サーバは既定ポートに上がる
  • reuseExistingServer: !isCI なので、既定ポートを無関係のプロセスが握っていると Playwright はそれを自分のサーバとみなす (port: 指定では TCP 応答しか見ず同一性確認が原理的に行われない)

scripts/dev.mjs:118-145 に同じ配線の前例があるので踏襲しました。editor は env (vite.config.ts は既に EDITOR_PORTserver.port + strictPort を、WORKERS_PORTVITE_API_URL を追従させる実装 — 受け口は実装済みで渡していなかっただけ)、workers は wrangler が env を読まないため --port

同一性 assert は入れていません。strictPort が立てば他人のプロセスが居座るポートでは起動が失敗するので、誤認の実害はそこで消えます。

ADR-0030 の自動ポート割当は scripts/dev.mjs (= npm run dev) 経路にしか効かず、e2e は各パッケージの dev script を直接叩くため恩恵がありません。#196 では解消していませんでした。 CI は reuseExistingServer: false なので影響はローカル開発のみです。

確認方法

  • actionlint .github/workflows/deploy.yml — 指摘なし

  • npm run lint / npm run typecheck -w @typedcode/e2e — green

  • ポート伝播を実測 (ローカル):

    起動 結果
    EDITOR_PORT=5183 WORKERS_PORT=8797 npm run dev -w @typedcode/editor 5183 で応答 (HTTP 200) / 5173 は無応答
    npm run dev -w @typedcode/workers -- --port 8797 8797 で応答 (HTTP 404 = ルート未定義で正常) / 8787 は無応答
  • deploy-preview が実際に通ることcommand: を戻した判断のゲート (1 回落として原因を特定した経緯そのもの)

Closes #239
Closes #198

#239 (3 点):

1. PR プレビューの pages deploy が github.head_ref を command 文字列へ直接
   展開していた。wrangler-action は command を child_process.exec() に渡す =
   /bin/sh が解釈するため、`;` `$` バッククォートを含むブランチ名で注入が
   成立しうる (同 repo の push 権限が要るので現実的な脅威は事故としての破損の
   ほう)。env 経由でシェル変数として渡し、参照はクォートする。同じ理由で
   github-script の command-output も process.env 参照に変えた (wrangler 出力に
   バッククォートや ${ が混ざるとスクリプトごと壊れて job が落ちる)。

2. top-level permissions が無く deploy.yml だけが取り残されていた
   (labeler / pr-title / freshness は宣言済み)。contents: read を明示する。
   リポジトリ設定は既に default_workflow_permissions: read なので実効の変化は
   無く、目的は明示性と将来の設定変更に対する防御。job level の 3 箇所は据え置き。

3. Playwright ブラウザのキャッシュが無く毎回 chromium を DL していた
   (リポジトリ全体に actions/cache がゼロ)。~/.cache/ms-playwright を
   npx playwright --version の実解決バージョンでキーして復元する。--with-deps が
   入れる OS パッケージはキャッシュ対象外なので install 自体は毎回走らせる。

#198: playwright.config の webServer が port: を宣言しているのに、起動コマンドへ
ポートを一切渡していなかった。E2E_EDITOR_PORT を指定しても実サーバは既定ポートに
上がり、reuseExistingServer 時は既定ポートの無関係プロセスを自分のサーバと誤認
しうる (port: 指定では TCP 応答しか見ない)。scripts/dev.mjs と同じ配線に揃え、
editor は env (vite.config 側の受け口は実装済みだった)、workers は wrangler が
env を読まないため --port で渡す。ADR-0030 の自動割当は npm run dev 経路にしか
効かないため #196 では解消していなかった。CI は reuseExistingServer: false なので
影響はローカル開発のみ。

Closes #239
Closes #198

Assisted-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added pkg:repo リポジトリ横断 (docs/CI/依存) pkg:e2e packages/e2e labels Aug 15, 2026
前コミットで #239 の指摘どおり env 経由に変えたが、CI の実測でこれが誤りと判明
した。wrangler-action v4 は command: をシェルに渡さずトークン分割して npx を
直接 exec するため、$CF_PROJECT_NAME が展開されず wrangler がプロジェクト名と
して文字列 "$CF_PROJECT_NAME" を受け取り deploy-preview が失敗した。

同時にこれは #239 子項目① の前提そのものを崩す。シェルが介在しないので
head_ref に含まれうる `;` `$` バッククォートは不活性で、git はブランチ名に空白を
許さないため引数分割も起きない。command: 側にコマンドインジェクションは無い。

一方 github-script の command-output は本物のテンプレートリテラル評価なので
env 経由のまま維持する (wrangler 出力にバッククォートや ${ が混ざると
スクリプトごと壊れて job が落ちる)。

次に読む人が同じ「修正」を当てて再びデプロイを壊さないよう、実測の根拠を
command: の直前にコメントで残した。

Assisted-by: Claude <noreply@anthropic.com>
@shinyaoguri shinyaoguri changed the title ci(repo): deploy の文字列直展開と permissions を締め、Playwright キャッシュと e2e のポート伝播を足す (#239 #198) ci(repo): deploy の PR コメント経路と permissions を締め、Playwright キャッシュと e2e のポート伝播を足す (#239 #198) Aug 15, 2026
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Name URL
Preview https://faa4b97e.typedcode.pages.dev

Deployed from commit 948a8f5
API: staging Workers

@shinyaoguri
shinyaoguri merged commit 07743a4 into main Aug 15, 2026
9 checks passed
@shinyaoguri
shinyaoguri deleted the ci/p3-deploy-hardening-and-e2e-ports branch August 15, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg:e2e packages/e2e pkg:repo リポジトリ横断 (docs/CI/依存)

Projects

None yet

1 participant