From 41e8b6c4790d31fbcd7cddae0227f000f49386e3 Mon Sep 17 00:00:00 2001 From: s-hirano-ist Date: Wed, 3 Jun 2026 21:23:43 +0900 Subject: [PATCH 1/2] ci(renovate): self-host Renovate via GitHub App to escape Mend Cloud OOM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mend Cloud の無料 Community 枠は 1 job = 3GB cap で、本モノレポ(pnpm@11 / lockfile 17,620行)の install / lockFileMaintenance が kernel-out-of-memory で 落ちていた。toolSettings.nodeMaxMemory / ignoreScripts では頭打ちのため、 GitHub Actions の self-host (runner 16GB) へ移行する。 過去の PAT ベース self-host 版(全 Dependabot 化で削除済み)の知見を踏襲しつつ、 より安全な専用 GitHub App + 短命トークンで再構築: - .github/workflows/renovate.yaml を新規追加 - actions/create-github-app-token で短命トークン発行 (App PR は ci.yaml を発火) - RENOVATE_PLATFORM_COMMIT: enabled で Verified コミット (gitAuthor 固定不要) - RENOVATE_FORCE で workflow_dispatch 時は schedule(月曜朝) を自動バイパス - issues/pull_request トリガーは自走ループ回避のため意図的に除外 - cron "0 16 * * *" (01:00 JST) で週次/四半期の両 schedule 窓を自動カバー - NODE_OPTIONS=6144 (Renovate本体) + nodeMaxMemory=4096 (pnpm) で二重 OOM 防止 - .github/renovate.json5: nodeMaxMemory 2048 -> 4096、コメントを self-host 前提に更新 - renovate-todo.md: GitHub App 作成 / Secrets 登録 / Mend 撤去 / 検証の手動手順 Co-Authored-By: Claude Opus 4.8 --- .github/renovate.json5 | 13 +++--- .github/workflows/renovate.yaml | 71 ++++++++++++++++++++++++++++++++ renovate-todo.md | 72 +++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/renovate.yaml create mode 100644 renovate-todo.md diff --git a/.github/renovate.json5 b/.github/renovate.json5 index fbc91e290..7a2015945 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -17,16 +17,17 @@ // - lockFileMaintenance: 四半期に pnpm-lock 全リフレッシュ // github-actions / docker-compose は pnpm 非依存のため .github/dependabot.yml が担当。 enabledManagers: ["npm", "mise", "nvm"], - // Mend Cloud / self-host いずれでも pnpm install の lifecycle scripts (sharp / + // self-host runner での pnpm install の lifecycle scripts (sharp / // @prisma/engines / @sentry/cli / esbuild) によるメモリ消費を抑える保険。 // CI (--frozen-lockfile) と本番 deploy 側の install では通常通りバイナリを取得する。 ignoreScripts: true, - // Mend-hosted の kernel-out-of-memory 対策 (公式 FAQ 推奨)。pnpm の Node プロセスに - // --max-old-space-size=2048(MB) を渡し、V8 ヒープを Mend のコンテナ上限より下で - // 頭打ちにして積極 GC させ、OOM Killer による kill を回避する。 - // まだ落ちるなら値を下げる (1536) / JS heap OOM に変われば 1 回の作業量を削る。 + // self-host runner (GitHub Actions / ubuntu-24.04, 7GB RAM) での pnpm メモリ上限。 + // pnpm の Node プロセスに --max-old-space-size=4096(MB) を渡し、V8 ヒープを runner の + // 物理メモリより十分下で頭打ちにして OOM を回避する (.github/workflows/renovate.yaml)。 + // Mend Cloud 無料枠の 3GB コンテナでは OOM Killer に殺されていたため self-host へ移行済み。 + // モノレポ規模が増えて落ちるようなら branchConcurrentLimit を下げるか値を調整する。 toolSettings: { - nodeMaxMemory: 2048, + nodeMaxMemory: 4096, }, dependencyDashboard: true, branchConcurrentLimit: 3, diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml new file mode 100644 index 000000000..dd9aa99b3 --- /dev/null +++ b/.github/workflows/renovate.yaml @@ -0,0 +1,71 @@ +name: renovate + +permissions: {} + +on: + schedule: + # 毎日 16:00 UTC = 翌 01:00 JST に起動。実際の PR 生成は .github/renovate.json5 の + # schedule / timezone(Asia/Tokyo) が gate する。この時刻なら + # - "before 11am on monday" → 月曜 01:00 JST でヒット + # - 四半期 "before 5am on the 1st" → 1日 01:00 JST でヒット + # の両方の窓を取りこぼさない(窓外の日は Renovate 側で no-op になるだけ)。 + - cron: "0 16 * * *" + workflow_dispatch: + inputs: + logLevel: + description: ログレベル + type: choice + default: info + options: [info, debug] + dryRun: + description: dry-run(書き込みなしでログ出力のみ) + type: boolean + default: false + # NOTE: `issues: edited` / `pull_request` トリガーは意図的に外している。Renovate 自身が + # Dependency Dashboard issue の body を毎回更新するため、これらを残すと + # 「run が dashboard を更新 → issues:edited が発火 → 別の run が起動」の自走ループになり + # 大量の `repository-changed` abort を生む。Dashboard checkbox を toggle しても次の + # scheduled / workflow_dispatch run で読み取られるので機能は失われない(即時反応しなくなるだけ)。 + +concurrency: + group: renovate + cancel-in-progress: false + +jobs: + renovate: + runs-on: ubuntu-24.04 + timeout-minutes: 60 + # 実際の repo write 権限は GitHub App トークンが持つため job の GITHUB_TOKEN は不要。 + permissions: {} + steps: + # 専用 GitHub App の短命トークンを発行。GITHUB_TOKEN と異なり App トークンで + # 作成した PR は ci.yaml 等のワークフローを発火できる(automerge 前提のため必須)。 + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + app-id: ${{ secrets.RENOVATE_APP_ID }} + private-key: ${{ secrets.RENOVATE_APP_PRIVATE_KEY }} + + # self-host 実行。repo 設定 .github/renovate.json5 は Renovate が自動検出する + # (configurationFile はグローバル設定用なので渡さない)。 + - name: Self-hosted Renovate + uses: renovatebot/github-action@693b9ef15eec82123529a37c782242f091365961 # v46.1.14 + with: + token: ${{ steps.app-token.outputs.token }} + env: + RENOVATE_REPOSITORIES: ${{ github.repository }} + RENOVATE_PLATFORM: github + # App トークンで GitHub Contents API 経由の commit を行う。commit は App bot に + # 自動帰属し "Verified" バッジが付くため、PAT 運用で必要だった gitAuthor 固定は不要。 + RENOVATE_PLATFORM_COMMIT: enabled + # Mend Cloud 無料枠は 3GB cap で OOM kill されていた。ubuntu-24.04 runner は + # 十分なメモリ(16GB)を持つので Renovate プロセス自身のヒープに 6GB 割り当てる。 + # pnpm 子プロセス側の上限は renovate.json5 の toolSettings.nodeMaxMemory(4096) が担保。 + NODE_OPTIONS: --max-old-space-size=6144 + LOG_LEVEL: ${{ inputs.logLevel || 'info' }} + # dryRun=true のとき 'full'、それ以外(schedule 実行含む)は空=通常実行。 + RENOVATE_DRY_RUN: ${{ inputs.dryRun && 'full' || '' }} + # schedule trigger 以外(workflow_dispatch)はユーザの能動的なアクションなので、 + # renovate.json5 の schedule を無視して即時実行する(force で schedule を空に上書き)。 + RENOVATE_FORCE: ${{ github.event_name != 'schedule' && '{"schedule":[]}' || '' }} diff --git a/renovate-todo.md b/renovate-todo.md new file mode 100644 index 000000000..33a4ff67c --- /dev/null +++ b/renovate-todo.md @@ -0,0 +1,72 @@ +# Renovate self-host 移行 TODO(手動セットアップ) + +Mend Cloud 無料枠(1 job = 3GB)の `kernel-out-of-memory` を回避するため、Renovate を +GitHub Actions の self-host(`.github/workflows/renovate.yaml`)へ移行した。runner は 16GB RAM の +ため Mend のメモリ上限から解放される。認証は短命トークンの **専用 GitHub App** を使う。 + +このファイルは下記の手動ステップが完了したら削除すること。 + +## 背景(なぜ App 版か) + +- 過去に PAT ベースの self-host 版が存在したが、全 Dependabot 化の際に削除 → その後 + 「Dependabot が pnpm 11 非対応」で npm を Renovate に差し戻した際、self-host を復活させず + Mend Cloud に戻ったため OOM が再発していた。 +- 今回は PAT より安全な GitHub App(短命トークン・`platformCommit` で Verified コミット)で再構築。 + +--- + +## 手動ステップ(GitHub UI 操作のため要手動) + +### 1. 専用 GitHub App を作成 +GitHub → Settings → Developer settings → GitHub Apps → **New GitHub App** + +- [ ] **Repository permissions** を設定 + - Contents: **Read and write**(ブランチ・コミット・lockfile 更新) + - Pull requests: **Read and write**(PR 作成・automerge 有効化) + - Issues: **Read and write**(Dependency Dashboard issue の維持) + - Metadata: Read-only(必須・自動付与) + - ※ `enabledManagers` は npm/mise/nvm のみでワークフローは触らないため **Workflows 権限は不要** +- [ ] **Webhook** の "Active" を **オフ**(cron / workflow_dispatch 起動なのでイベント購読不要) +- [ ] Where can this app be installed: **Only on this account** +- [ ] 作成後、**Private key を生成**(`.pem` をダウンロード)し、**App ID** を控える +- [ ] **Install App** で `s-hirano-ist/s-private` にインストール + +### 2. Secrets を登録 +```bash +gh secret set RENOVATE_APP_ID --body "" +gh secret set RENOVATE_APP_PRIVATE_KEY < ~/Downloads/.private-key.pem +``` +- [ ] `RENOVATE_APP_ID` 登録 +- [ ] `RENOVATE_APP_PRIVATE_KEY` 登録 + +### 3. リポジトリ設定 +- [ ] Settings → General → Pull Requests → **Allow auto-merge** を有効化 + (`platformAutomerge: true` の前提) + +### 4. Mend Renovate App を撤去(重複 PR 防止) +- [ ] GitHub → Settings → Integrations → Applications → **Renovate** → Configure → + `s-private` をアクセス対象から外す(または Uninstall) + +--- + +## 検証(手動 1〜4 完了後) + +- [ ] **dry-run**: `gh workflow run renovate.yaml -f dryRun=true -f logLevel=debug` + → Actions ログでリポジトリが処理され、OOM もエラーも無く完走することを確認 +- [ ] **本実行**: `gh workflow run renovate.yaml` → App ユーザーが `renovate/*` ブランチで + PR を作成し、`dependencies` ラベルが付くことを確認 +- [ ] **CI 連動**: 作成された Renovate PR 上で既存 `ci.yaml` が発火していることを確認 + (= App トークンがワークフローを起動できている証拠。`GITHUB_TOKEN` では起動しない) +- [ ] **automerge**: devDependencies / mise の patch・minor PR が CI 通過後に自動マージされ、 + main の branch protection と矛盾しないことを確認 +- [ ] **Dashboard**: Dependency Dashboard issue が self-host により更新されることを確認 +- [ ] **重複なし**: Mend 撤去後、Mend 由来の PR が新規に出ないことを数日観察 + +--- + +## 後片付け + +- [ ] 移行確認後、旧 PAT secret `RENOVATE_TOKEN` を削除(App 版では未使用) + `gh secret delete RENOVATE_TOKEN` +- [ ] Mend が残した既存の `renovate/*` リモートブランチを整理(self-host が作り直す) +- [ ] このファイル `renovate-todo.md` を削除 From 9d4fd0008cc98b27cdfdab476d12845ac7938d9c Mon Sep 17 00:00:00 2001 From: s-hirano-ist Date: Wed, 3 Jun 2026 21:26:39 +0900 Subject: [PATCH 2/2] ci(renovate): scope App token to least privilege (ghalint policy 010) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ghalint の github_app_should_limit_permissions に従い、create-github-app-token の生成トークンを permission-contents/pull-requests/issues: write に限定する。 --- .github/workflows/renovate.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index dd9aa99b3..67e9c5260 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -46,6 +46,13 @@ jobs: with: app-id: ${{ secrets.RENOVATE_APP_ID }} private-key: ${{ secrets.RENOVATE_APP_PRIVATE_KEY }} + # 生成トークンを最小権限に限定(metadata:read は常時付与)。 + # contents : ブランチ・コミット・lockfile 更新 + # pull-requests : PR 作成・automerge 有効化 + # issues : Dependency Dashboard issue の維持 + permission-contents: write + permission-pull-requests: write + permission-issues: write # self-host 実行。repo 設定 .github/renovate.json5 は Renovate が自動検出する # (configurationFile はグローバル設定用なので渡さない)。