AstroをCloudflare Pagesへ出す前のRelease Gate設計とAIエージェント運用例
Astroのcheck・build・生成物確認・承認・本番確認を、GitHub ActionsとCloudflare Pages Direct Uploadで再利用できる公開ゲートに整理。AIエージェントで記事公開を回す運用例も載せます。
結論
AstroをCloudflare Pagesへ安全に出すRelease Gateは、npm ci → npm run check → npm run build → 必須生成物確認 → 差分・承認 → deploy → 公開URL確認の順に分けます。本番資格情報は、検証を通過したdeploy jobだけへ渡します。
筆者が2026年8月13日に確認したcodeagent.jpの非公開リポジトリでは、workflow定義はmainへのpushまたは手動実行で npm ci、npm run build、Cloudflare Pages Direct Uploadを行う構成でした。一方、npm run check と公開後HTTP確認は含まれていませんでした。このスナップショットは読者が公開URLから検証できないため、サイト固有の事例として明記し、一般的な推奨はAstro、Cloudflare、GitHubの公開公式Docsで裏付けます。既存workflowを変更した、または本番へ公開したという報告ではありません。
この記事の対象読者
- Astroの静的サイトをCloudflare PagesへGitHub Actionsで公開している人
- build成功だけでは不安で、型・コンテンツ・生成物まで検査したい人
- main pushの自動公開を維持しながら、公開前に確実な停止点を作りたい人
- 複数サイトへ共通のRelease Gateを再利用したいチーム
- AIエージェントに記事公開やSEO修正を任せつつ、公開の判定は機械的な検査で行いたい人
AIエージェントに調査からSEO確認までを任せた場合の役割分担は、後半の運用例にまとめました。
- Gate 1再現npm ciでlockfileどおりに依存関係を入れる。
- Gate 2静的検査npm run checkで型とコンテンツの診断を通す。
- Gate 3生成npm run buildと必須ファイル確認を通す。
- Gate 4承認差分、公開日、draft、出典、未関係変更を確認する。
- Gate 5公開資格情報を持つjobだけがPagesへ送る。
- Gate 6検証公開URL、canonical、sitemap、導線を確認する。
workflowの事実を棚卸しする(2026年8月13日時点)
対象は、筆者がアクセスできる非公開リポジトリ内の .github/workflows/deploy-cloudflare-pages.yml と package.json です。2026年8月13日時点の状態は次の通りです。以下は匿名化した構成の要約であり、外部から検証できる公開一次資料ではありません。なお codeagent.jp では、2026年7月下旬に GitHub Actions の利用枠の上限でこの workflow が動かなくなり、以降はローカルから npx wrangler pages deploy で公開しています。
| 項目 | 当時の状態 | Release Gate上の評価 |
|---|---|---|
| トリガー | main push、workflow_dispatch | 自動公開として明確 |
| 同時実行 | 固定group、cancel-in-progress: true | 古い実行の競合を抑える |
| 権限 | contents: read、deployments: write | 必要範囲を明示 |
| Node | .nvmrcをsetup-node@v6で利用 | ローカルとCIを揃えやすい |
| 依存導入 | npm ci | lockfile再現性あり |
| 静的検査 | npm run checkなし | PR側の必須ゲートが必要 |
| ビルド | npm run build | Astro buildとPagefind生成を実行 |
| デプロイ | Wrangler Action v3、Wrangler 4、dist | Pages Direct Uploadに一致 |
| 本番資格情報 | GitHub Secretsからdeploy stepへ渡す | deploy jobへ限定したい |
| 公開後確認 | deployment URLを表示 | HTTP・内容確認を追加したい |
ここで大事なのは、「workflowに不足がある」ことと「今すぐ同じファイルへすべて詰め込む」ことは別だという点です。main pushで即デプロイされる構成では、公開前の停止点をPRに置く方が明確です。
なぜcheckとbuildを分けるのか
Astro CLI公式Docsによると、astro check は .astro ファイルなどの診断・型検査を行い、エラーがあれば終了コード1で終わるCI向けコマンドです。astro build はデプロイ用のサイトを生成し、静的サイトでは既定で dist/ へ出力します。
役割を一つにまとめず、失敗理由を分けます。
| コマンド | 確認するもの | 失敗時の扱い |
|---|---|---|
npm ci | lockfileと依存関係の再現 | 環境またはlockfileを直す |
npm run check | Astro診断、型、コンテンツschema | コード・frontmatterを直す |
npm run build | 全ルート生成、MDX評価、Pagefind | ビルド・リンク・生成処理を直す |
| 生成物assert | dist内の必須ファイル | 出力設定・slug・draftを直す |
| 公開後smoke | 配信されたHTTPとメタ情報 | デプロイ停止・切り戻しを判断 |
npm run buildが成功しても、checkを実行した事実にはなりません。反対に、check成功だけでも全ルートの生成と検索インデックス作成は保証できません。
再利用可能なRelease Gateの設計
検証だけを再利用workflowへ分離すると、本番secretを使わずに複数サイトから呼べます。以下は設計例であり、このリポジトリへ追加済みのworkflowではありません。
name: Reusable Astro Release Gate
on: workflow_call: inputs: required_artifact: description: Build後に存在必須とするファイル required: false type: string default: dist/index.html
permissions: contents: read
jobs: validate: runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version-file: .nvmrc cache: npm - run: npm ci - run: npm run check - run: npm run build - name: Assert required artifact shell: bash env: REQUIRED_ARTIFACT: ${{ inputs.required_artifact }} run: | artifact="$(realpath -m -- "$REQUIRED_ARTIFACT")" dist_root="$(realpath -- dist)" case "$artifact" in "$dist_root"/*) ;; *) echo "required_artifact must stay under dist/" >&2; exit 1 ;; esac test -f "$artifact"このゲートにはCloudflareのトークンもアカウントIDも渡しません。呼び出し元はPRでゲートを実行し、main側のdeploy jobはゲート済みコミットだけを扱います。サイト固有の必須生成物はinputで切り替えます。workflow inputはシェルへ直接展開せず環境変数に渡し、realpathでdist/の外へ出ないことも確認します。
再利用性を高める境界は次の通りです。
- 共通化する: Node設定、
npm ci、check、build、タイムアウト、成果物assert - サイト側に残す: 必須URL、canonical、sitemap名、環境変数、承認者
- deploy側にだけ置く: Cloudflare API token、account ID、project name
- 公開後に置く: 配信URL、コンテンツ本文、キャッシュ、主要リンクのsmoke test
Cloudflare PagesのDirect Upload CIガイドも、GitHub Actionsでビルド・テストとWranglerデプロイを自動化できること、資格情報をGitHub Secretsへ置くことを示しています。
PRから公開までの具体手順
1. ローカル差分を限定する
記事公開なら対象MDX、必要な画像、意図した内部リンクだけが差分に入っているか確認します。未追跡・未コミットの別作業をビルドや公開へ混ぜません。AIエージェントに作業させた後は特に起きやすい問題なので、必要ならクリーンな作業コピーを作り、今回の差分だけをビルド・デプロイします。
git status --shortnpm cinpm run checknpm run buildTest-Path -LiteralPath dist/index.htmlTest-Path -LiteralPath dist/sitemap-index.xmlnpm ci は環境を更新するため、作業中の依存関係を保ちたい場合はクリーンな作業コピーやCIで実行します。生成物名は各サイトの設定に合わせてください。
2. 記事固有の生成物を確認する
公開slugが example-post なら、dist/posts/example-post/index.html の存在を確認します。本文タイトル、draft: false、公開日、canonical、構造化データ、内部リンクも生成HTMLから検証します。MDXの公開要件は記事のschemaに合わせます。
3. PRで再利用ゲートを必須にする
pull_requestで共通workflowを呼び、成功をbranch protectionまたはrulesetのrequired checkにします。Claude CodeのCI自動化例のようなAIエージェントを使う場合も、エージェントの完了報告ではなくCIの終了コードを判定根拠にします。
4. 承認時に公開条件を読む
レビューでは文章だけでなく、次を確認します。
- 公開対象ファイルと意図しない差分
draft、pubDate、sourceCheckedAt- 一次情報のURLと確認日
- 内部リンクの実在
- 著作権・機密・個人情報
- 検証ログと既知の未確認事項
5. main側でdeployする
2026年8月13日時点のcodeagent.jpのworkflow定義は、main push後に dist を pages deploy する構成でした。再利用ゲートを導入する場合は、PRで同一コミットを検証済みにするか、deploy workflow内のdeploy jobをvalidate jobへ依存させます。どちらの場合も、検証失敗時にはCloudflare secretへ到達させません。
6. 公開URLを確認する
workflowが表示するdeployment URLだけでなく、正規URLも確認します。
curl --fail --silent --show-error --location \ --output /tmp/article.html \ https://example.com/posts/example-post/
grep -F '<link rel="canonical" href="https://example.com/posts/example-post/">' \ /tmp/article.html実運用では、タイトル、canonical、sitemap収録、主要内部リンク、404ページ、必要な静的アセットまで確認します。プレビューURLと正規URLではキャッシュやドメイン設定が異なるため、両者を混同しません。
判断表:どこで止めるか
| 事象 | 自動判定 | 人間判断 | 対応 |
|---|---|---|---|
npm ci失敗 | 可能 | 原因確認 | deployしない |
npm run check失敗 | 可能 | 修正範囲確認 | deployしない |
npm run build失敗 | 可能 | 原因確認 | deployしない |
| 必須HTML・sitemap欠落 | 可能 | 出力要件確認 | deployしない |
| 未関係差分の混入 | 一部可能 | 必須 | PRを戻す |
| 出典未確認・日付不整合 | 一部可能 | 必須 | 公開を延期 |
| secretらしき値を検知 | 可能 | 必須 | 停止・失効・調査 |
| デプロイ後に非2xx | 可能 | 影響判断 | 再試行または切り戻し |
| canonical・本文が不一致 | 可能 | 影響判断 | 公開完了にしない |
GitHub ActionsのSecrets解説は、資格情報の権限を最小化すること、ログの自動マスキングが常に保証されるわけではないことを説明しています。secretを検証jobへ渡さず、deploy stepでも値をechoしない設計が基本です。
AIエージェントで公開作業を回す運用例
2026年4月に、同じ運営者が管理する RandaWorks - AIエージェントを活用して運営する日本史ゲーム・学習ツールサイト とcodeagent.jpの相互リンク、メタ情報、sitemap、Cloudflare Pagesへの公開確認をCodexに手伝わせた例です。Release Gateの手前で、何を人間が決め、何をエージェントに任せたかを示します。
RandaWorksは日本史ゲームと学習ツールのサイトで、読者は遊ぶ、学ぶ、問い合わせるために来ます。AIエージェントの実務メディアであるcodeagent.jpとは読者の目的が違うため、役割を次のように分けました。
- エージェントに任せる: 既存サイト構成の調査、About・Contact・Footerなど導線の確認、記事やページのメタ情報、sitemap・robots・Search Consoleの確認、Cloudflare Pagesへのデプロイ確認、本番URLでの表示確認
- 人間が決める: ブランドの見せ方、サイト同士の距離感、相互リンクの強さ
ここをエージェントに任せすぎると、全ページのフッターから無関係なサイトへ強く誘導するような不自然な構成になりやすいです。このときは、RandaWorks側はAboutの関連プロジェクト欄に控えめに置き、codeagent.jp側はAboutと関連記事から実践プロジェクトとして紹介し、問い合わせ窓口はRandaWorksのフォームに一本化しました。
進め方は、調査、差分作成、ビルド確認、公開確認の4段階です。この記事のゲートに当てはめると、調査と差分作成がGate 4の承認の前提づくり、ビルド確認がGate 1〜3、公開確認がGate 6に当たります。最初はファイルを変更させず、調査だけを依頼します。
RandaWorks と codeagent.jp の相互リンク方針を確認したいです。まだファイルは変更しないでください。
確認してください:- Aboutページの有無- Contactページの有無- Footerに外部リンクを置くべきか- 既存のトーンと合うリンク位置- 変更候補ファイル調査の結果を見て置き場所を決めたら、変更範囲と完了条件を明示します。AIエージェントは、明示しないと「関連リンクならフッターにも置こう」と判断することがあります。
RandaWorks側は /about/ の関連プロジェクト欄だけを変更してください。グローバルナビとフッターには追加しないでください。
codeagent.jp側は /about/ と関連記事から RandaWorks へリンクしてください。問い合わせ導線は RandaWorks のフォームに集約してください。
完了条件:- npm run build が成功する- /about/ にリンクが表示される- /contact/ の問い合わせ先が正しい- 本番URLで 200 が返る- 変更したリンクが意図したURLを指している「コードを書いたら終わり」ではなく、「公開後に正しいURLへつながる」までを完了条件にします。このRelease Gateに載せるなら、完了条件に npm run check も加え、エージェントの完了報告ではなく終了コードと公開URLで判定します。公開後のSearch Consoleとsitemapの確認は忘れやすいため、公開後チェックリストに入れておきます。
公開前チェックリスト
- 公開対象と未関係差分を分離した
-
npm ciがlockfileどおり成功した -
npm run checkが終了コード0で成功した -
npm run buildが終了コード0で成功した - 記事HTML、トップ、sitemapなど必須生成物がある
-
draft、公開日、一次情報確認日を確認した - 内部リンクとcanonicalが意図したURLを指し、アンカーテキストが説明的になっている
- PRのRelease Gateをmainの必須チェックにした
- 本番secretをdeploy job以外へ渡していない
- 公開後smoke testと切り戻し担当を決めた
公開後チェックリスト
- workflowが対象コミットで成功した
- deployment URLと正規URLが2xxを返した
- title、description、canonicalが正しい
- sitemapに公開URLが含まれる
- Search Consoleでのsitemap・公開URLの確認を作業に含めた
- 主要な内部リンクと静的アセットが取得できる
- 404、JavaScriptエラー、レイアウト崩れがない
- 問題発生時の停止・切り戻し記録を残した
Cloud型コーディングエージェントを公開フローへ組み込む場合も、誰が変更したかにかかわらず、同じゲートを通すことが重要です。
よくある質問
npm run buildが成功すればnpm run checkは不要ですか?
不要とはいえません。Astro公式Docsではastro checkは診断や型検査を行い、エラー時に終了コード1を返すCI向けコマンドです。buildと検出範囲が同じではないため、公開ゲートではcheckとbuildを別々に通します。
mainへのpushで自動デプロイする場合、どこで公開を止めますか?
mainへ入った時点でデプロイが始まるなら、停止点はmainの手前です。pull_requestでRelease Gateを必須チェックにし、ブランチ保護またはrulesetで成功したPRだけをmainへ入れる設計にします。
Cloudflare PagesのデプロイURLが出れば公開確認は完了ですか?
完了ではありません。URLの2xx応答、記事タイトル、canonical、sitemap、主要リンクを確認し、期待したコミットが配信されていることまで記録します。認証やキャッシュの影響があるサイトでは追加の確認も必要です。
AIエージェントに記事公開やSEO修正を任せるとき、どこまで任せますか?
調査、差分作成、ビルド確認、公開確認の4段階に分け、サイト構成の調査、内部リンクやメタ情報の編集、sitemapや本番URLの確認はエージェントに任せます。サイト同士の距離感、リンクの強さ、ブランドの見せ方は人間が決めます。完了の判定は、エージェントの報告ではなくcheck・buildの終了コードと公開URLの確認で行います。
まとめ
AstroのRelease Gateは、一つの巨大なdeploy workflowではなく、再現、静的検査、生成、承認、公開、公開後確認という停止可能な段階で作ります。astro check と astro build は役割が違うため両方を実行し、サイト固有の必須生成物も確認します。
2026年8月13日時点のcodeagent.jpのworkflowには、npm ci、build、Direct Upload、同時実行制御、最小限の権限がありました。一方、npm run check と公開後smoke testは含まれていませんでした。main pushで自動公開する構成なら、まずPRの再利用ゲートをmainの必須条件にし、通過したコミットだけへ本番資格情報を渡す設計にすると、自動公開を保ちながら明確な停止点を持てます。
AIエージェントに公開作業を任せる場合も、サイト同士の距離感やリンクの強さは人間が決め、完了の判定はエージェントの報告ではなく、ゲートの終了コードと公開URLの確認で行います。
検証メモと一次情報
- サイト固有のworkflowと
package.json: 筆者が2026年8月13日に非公開リポジトリのローカルスナップショットで確認(公開URLなし) - Astro Docs: CLI Commands
- Astro Docs: Deploy your Astro Site to Cloudflare
- Cloudflare Pages: Use Direct Upload with continuous integration
- GitHub Docs: Workflow syntax for GitHub Actions
- GitHub Docs: Secrets
関連して読む
seo・astroを続けて読む
· 参考リンク 7件llms.txtの設置と検証:Astroでの生成、配信・リンク確認、クロールの観察
llms.txt v2の提案を基に、書式と設置場所、Astroでの自動生成、配信・書式・リンクの検証、Search Consoleでの観察を整理します。検索効果とは分けて扱います。
codex・個人開発を続けて読む
· 参考リンク 2件仕様駆動でAIエージェントに実装させる — SPEC.md・依頼テンプレート・よくある失敗5つ
大きめの機能は仕様を固める会話と実装する会話を分けると手戻りが減ります。SPEC.mdを書かせて新セッションで実装させる手順に加え、依頼テンプレートとClaude Code/Codexでよくある失敗5つを整理します。
この記事の情報・検証メモ
- 公開日
- 情報確認
- 参考リンク
- 5件
- 更新性
- 定期更新
仕様・料金・提供範囲が変わりやすいテーマは、公開日・更新日・情報確認日を分けて管理します。 導入前には必ず記事末尾の一次情報と公式ドキュメントで最新状況を確認してください。
一次情報・参考リンク
- Astro Docs: CLI Commands https://docs.astro.build/en/reference/cli-reference/
- Astro Docs: Deploy your Astro Site to Cloudflare https://docs.astro.build/en/guides/deploy/cloudflare/
- Cloudflare Pages docs: Use Direct Upload with continuous integration https://developers.cloudflare.com/pages/how-to/use-direct-upload-with-continuous-integration/
- GitHub Docs: Workflow syntax for GitHub Actions https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
- GitHub Docs: Secrets https://docs.github.com/en/actions/concepts/security/secrets