diff --git a/README.md b/README.md index 97a9316..620d7cb 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ headlamp が 1 文字なのは、規則どおりだと head + lamp でも hubble | [`3proxy/`](apps/3proxy/) | 3proxy (国内IP経由の HTTPS フォワードプロキシ) | | [`k8up/`](apps/k8up/) | バックアップ(restic → Cloudflare R2)。**Talos でホストのスクリプトが使えなくなる**ぶんの受け皿 | | [`infisical/`](apps/infisical/) [`infisical-operator/`](apps/infisical-operator/) [`infisical-push-bridge/`](apps/infisical-push-bridge/) | 秘密の配布。本体は `bootstrap/` にあり、ここには公開経路と operator と即時反映のブリッジ | +| [`renovate/`](apps/renovate/) | Renovate(GitHub の danything・5ym と Forgejo の doa の全リポジトリの依存を上げる PR)。CronJob で 15 分おき。**秘密の入れ方は [apps/renovate/README.md](apps/renovate/README.md)** | | [`headlamp/`](apps/headlamp/) | Kubernetes の Web UI(`h.doany.io`、Portainer の置き換え)。認証は Entra、権限は `bootstrap/apiserver/` | | [`rybbit/`](apps/rybbit/) | Rybbit(`rt.doany.io`、アクセス解析。クッキー無し)+ ClickHouse + PostgreSQL + Redis。トドロクの離脱をファネル・ジャーニー・セッションリプレイで見る。**使い始めは [apps/rybbit/README.md](apps/rybbit/README.md)** | diff --git a/apps/adguardhome/renovate-post-upgrade.sh b/apps/adguardhome/renovate-post-upgrade.sh index 03b4c22..bf78356 100755 --- a/apps/adguardhome/renovate-post-upgrade.sh +++ b/apps/adguardhome/renovate-post-upgrade.sh @@ -7,9 +7,9 @@ # 読めない設定なら失敗する(= PR の postUpgradeTasks が落ちて気づける)。書き直したら config.yaml に戻し、 # deployment.yaml の doany.io/config-sha256 も合わせる(CI の adguard-config が見る)。 # -# 動くのは Renovate のコンテナ(ghcr.io/renovatebot/renovate、5ym/repo-config の renovate.yml)の中、リポジトリの直下。 +# 動くのは Renovate のコンテナ(ghcr.io/renovatebot/renovate、apps/renovate/renovate.yaml の CronJob)の中、リポジトリの直下。 # AdGuard の版は deployment.yaml のイメージのタグ(Renovate が上げた後の値)から取り、公式のチェックサムと照らしてから使う。 -# 許可は repo-config の renovate.yml の RENOVATE_ALLOWED_COMMANDS +# 許可は apps/renovate/renovate.yaml の RENOVATE_ALLOWED_COMMANDS set -euo pipefail cd "$(dirname "$0")" diff --git a/apps/renovate/README.md b/apps/renovate/README.md new file mode 100644 index 0000000..27e7458 --- /dev/null +++ b/apps/renovate/README.md @@ -0,0 +1,41 @@ +# renovate + +Renovate を CronJob で回す(2026-10-16〜)。GitHub の `danything` と `5ym`、Forgejo(fj.doany.io)の `doa` の全リポジトリ。 +設定は各リポジトリの `renovate.json`(共通は `github>5ym/repo-config`)。 + +それまでは GitHub Actions(5ym/repo-config の `renovate.yml`)と Forgejo Actions(doa/renovate)で毎時回していたが、 +GitHub の schedule は 15〜40 分遅れ、丸ごと飛ばされることもあった。 + +| CronJob | 対象 | 時刻(毎時) | +| --- | --- | --- | +| `renovate-danything` | GitHub の danything | 2・17・32・47 分 | +| `renovate-5ym` | GitHub の 5ym | 7・22・37・52 分 | +| `renovate-forgejo` | Forgejo の doa | 12・27・42・57 分 | + +**Job はいつも成功で終わる**(失敗で CronJob が Degraded になると、ArgoCD が gitops の同期を止めるため。 +[renovate.yaml](renovate.yaml) の冒頭)。うまく動いているかはログで見る: + +```shell +tools/t.ps1 kubectl -n renovate get jobs +tools/t.ps1 kubectl -n renovate logs job/<名前> +# 待たずに 1 回回す +tools/t.ps1 kubectl -n renovate create job --from=cronjob/renovate-5ym renovate-5ym-manual +``` + +## 秘密 + +Infisical の `/renovate/renovate-secrets`。**どれも無いあいだは、その CronJob は何もせずに終わる。** + +| キー | 中身 | 使う CronJob | +| --- | --- | --- | +| `github-app-private-key` | GitHub App `doa-renovate` の秘密鍵(PEM をそのまま)。App の設定画面の Private keys で作る | danything・5ym | +| `forgejo-token` | Forgejo のユーザー `renovate` のトークン(チーム `bots` = 全リポジトリに書き込み) | forgejo | +| `github-com-token` | 任意。権限なしの GitHub のトークン。github.com のリリースノートやタグを読むときの回数制限(匿名 60 回/時)よけ | forgejo | + +GitHub のトークンは実行のたびに App の鍵から作る(1 時間で切れる。[renovate.yaml](renovate.yaml) の `github-app-token.mjs`)。 + +## クラスタが落ちているとき + +Renovate も止まる。もとの workflow は `workflow_dispatch` だけ残してあるので、急ぐときは手で回す +(GitHub は 5ym/repo-config の Actions → Renovate、Forgejo は doa/renovate の Actions)。 +**CronJob と同時に走らせないこと**(同じリポジトリに 2 つの Renovate が触る)。 diff --git a/apps/renovate/namespace.yaml b/apps/renovate/namespace.yaml new file mode 100644 index 0000000..0d9dc4f --- /dev/null +++ b/apps/renovate/namespace.yaml @@ -0,0 +1,9 @@ +# PSA は restricted で足りる(Renovate のイメージは非 root の 12021 で動き、hostPath も特権も使わない)。 +apiVersion: v1 +kind: Namespace +metadata: + name: renovate + labels: + pod-security.kubernetes.io/enforce: restricted + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/warn: restricted diff --git a/apps/renovate/renovate-secrets.yaml b/apps/renovate/renovate-secrets.yaml new file mode 100644 index 0000000..34845ab --- /dev/null +++ b/apps/renovate/renovate-secrets.yaml @@ -0,0 +1,32 @@ +# Secret renovate-secrets は Infisical (il.doany.io) のフォルダ /renovate/renovate-secrets にあり、 +# Infisical 純正 operator (bootstrap/infisical-operator) が Secret にする。キーは README.md の表。 +# CronJob は Secret を毎回読み直すので、値を Infisical で書き換えれば次の実行から効く(auto-reload は要らない)。 +apiVersion: secrets.infisical.com/v1alpha1 +kind: InfisicalSecret +metadata: + name: renovate-secrets + namespace: renovate + # 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は + # CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。 + # bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。 + annotations: + argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true +spec: + hostAPI: http://infisical.infisical.svc:8080/api + authentication: + kubernetesAuth: + identityId: f2bc3416-f196-4626-9bf3-c11693b32cc6 + autoCreateServiceAccountToken: true + serviceAccountRef: + name: infisical-auth + namespace: infisical + secretsScope: + projectSlug: doa + envSlug: prod + secretsPath: /renovate/renovate-secrets + recursive: false + managedKubeSecretReferences: + - secretName: renovate-secrets + secretNamespace: renovate + # Orphan: CR を消しても Secret は残す(移行や再作成で稼働中の Pod を巻き込まない) + creationPolicy: Orphan diff --git a/apps/renovate/renovate.yaml b/apps/renovate/renovate.yaml new file mode 100644 index 0000000..7f17026 --- /dev/null +++ b/apps/renovate/renovate.yaml @@ -0,0 +1,310 @@ +# Renovate を自前で回す。danything と 5ym の GitHub の全リポジトリと、Forgejo(fj.doany.io)の doa の全リポジトリ。 +# +# それまでは GitHub Actions(5ym/repo-config の renovate.yml)と Forgejo Actions(doa/renovate)で毎時回していたが、 +# GitHub の schedule は 15〜40 分遅れるうえに丸ごと飛ばされることがあった(2026-10-12 に数えた)。 +# CronJob なら時刻どおりに走る。**クラスタが落ちている間は止まる**ので、両方の workflow は +# workflow_dispatch だけ残して手で回せるようにしてある(README.md)。 +# +# 1 本の CronJob が 1 つの owner を受け持つ(GitHub App のトークンがインストールごとに分かれるため。 +# Actions の matrix と同じ)。15 分おきで、3 本は 5 分ずつずらす。1 回 3〜7 分で終わる。 +# +# **Job はいつも成功で終える。** Renovate が非ゼロで終わっても、トークンが作れなくても exit 0。 +# Job が失敗すると CronJob が Degraded になり、ArgoCD が gitops の同期を retry に入れて +# apps/ の更新が止まる(2026-09-12 に k8up-notify で実際に起きた。apps/k8up/notify.yaml の末尾)。 +# 失敗はログに残す: `kubectl -n renovate logs job/<名前>`。Job はいつも成功なので、ログを見られるよう成功の Job を 3 回分残す。 +apiVersion: v1 +kind: ConfigMap +metadata: + name: renovate-scripts + namespace: renovate +data: + run.sh: | + # CronJob の入口。RENOVATE_PLATFORM でトークンの取り方を変えて renovate を流す。 + # 何があっても exit 0(理由は renovate.yaml の冒頭)。 + set -uo pipefail + case "$RENOVATE_PLATFORM" in + github) + if [ -z "${APP_PRIVATE_KEY:-}" ]; then + echo "renovate-secrets に github-app-private-key が無い。Infisical に入れるまで何もしない(README.md)" >&2 + exit 0 + fi + if ! RENOVATE_TOKEN=$(node /scripts/github-app-token.mjs); then + echo "GitHub App のトークンを作れなかった(上のエラー)" >&2 + exit 0 + fi + unset APP_PRIVATE_KEY + ;; + forgejo) + if [ -z "${RENOVATE_TOKEN:-}" ]; then + echo "renovate-secrets に forgejo-token が無い。Infisical に入れるまで何もしない(README.md)" >&2 + exit 0 + fi + ;; + esac + export RENOVATE_TOKEN + renovate + rc=$? + [ "$rc" -eq 0 ] || echo "renovate が $rc で終わった(Job は成功にしておく。renovate.yaml の冒頭)" >&2 + exit 0 + github-app-token.mjs: | + // GitHub App doa-renovate のインストールトークンを作って標準出力に出す + // (Actions の頃の actions/create-github-app-token の代わり)。 + // App の JWT(RS256、iss は client ID)で OWNER のインストールを探し、トークンと交換する。 + // トークンは 1 時間で切れる。Job の activeDeadlineSeconds はそれより短くしてある。 + import { sign } from "node:crypto"; + + const { APP_CLIENT_ID, APP_PRIVATE_KEY, OWNER } = process.env; + const b64 = (o) => Buffer.from(JSON.stringify(o)).toString("base64url"); + const now = Math.floor(Date.now() / 1000); + // iat を 60 秒戻すのは GitHub の推奨(時計のずれ)。exp は 10 分が上限 + const body = `${b64({ alg: "RS256", typ: "JWT" })}.${b64({ iat: now - 60, exp: now + 540, iss: APP_CLIENT_ID })}`; + const jwt = `${body}.${sign("RSA-SHA256", Buffer.from(body), APP_PRIVATE_KEY).toString("base64url")}`; + + const api = async (method, path) => { + const r = await fetch(`https://api.github.com${path}`, { + method, + headers: { + Authorization: `Bearer ${jwt}`, + Accept: "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", + }, + }); + if (!r.ok) throw new Error(`${method} ${path}: ${r.status} ${await r.text()}`); + return r.json(); + }; + + const installs = await api("GET", "/app/installations?per_page=100"); + const inst = installs.find((i) => i.account.login.toLowerCase() === OWNER.toLowerCase()); + if (!inst) throw new Error(`${OWNER} に App が入っていない(あるのは ${installs.map((i) => i.account.login).join(", ")})`); + process.stdout.write((await api("POST", `/app/installations/${inst.id}/access_tokens`)).token); +--- +# GitHub の 2 本で共通の設定。中身は Actions の頃の renovate.yml の env と同じ +apiVersion: v1 +kind: ConfigMap +metadata: + name: renovate-github + namespace: renovate +data: + RENOVATE_PLATFORM: github + # GitHub App doa-renovate(danything の org が持ち主。5ym にもインストールしてある)。client ID は秘密ではない + APP_CLIENT_ID: Iv23liZjExRcK6lxJueN + # App のトークンからは自分のユーザーを引けないので明示する。id は + # `gh api users/doa-renovate%5Bbot%5D --jq .id` + RENOVATE_GIT_AUTHOR: doa-renovate[bot] <336970664+doa-renovate[bot]@users.noreply.github.com> + # コミットを API で作る = App の署名付き(Verified)になる + RENOVATE_PLATFORM_COMMIT: enabled + RENOVATE_AUTODISCOVER: "true" + # renovate.json の無いリポジトリには、共有プリセットを使う renovate.json を + # 足す onboarding の PR を出す。マージされるまでは依存の PR は出さない + RENOVATE_ONBOARDING: "true" + RENOVATE_ONBOARDING_CONFIG: '{"$schema":"https://docs.renovatebot.com/renovate-schema.json","extends":["github>5ym/repo-config"]}' + RENOVATE_REQUIRE_CONFIG: required + # postUpgradeTasks で流してよいコマンド(正規表現。これに合わないものは Renovate が拒む)。 + # pulumi/ は bun.lock を Renovate が作れない(SDK を pulumi install でしか作れない)ので、 + # スクリプトで pulumi install させる(pulumi/README.md)。 + # AdGuard Home の版上げでは、新しい版に config.yaml を移行させる(apps/adguardhome/renovate-post-upgrade.sh) + RENOVATE_ALLOWED_COMMANDS: '["^bash pulumi/renovate-post-upgrade\\.sh$", "^bash apps/adguardhome/renovate-post-upgrade\\.sh$"]' + LOG_LEVEL: info +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: renovate-danything + namespace: renovate +spec: + schedule: "2-59/15 * * * *" + # 前の実行が終わっていなければ飛ばす(同じリポジトリに 2 つの Renovate が同時に触らない) + concurrencyPolicy: Forbid + startingDeadlineSeconds: 600 + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + jobTemplate: + spec: + backoffLimit: 0 + # トークンは 1 時間で切れる。それより前に止める + activeDeadlineSeconds: 2700 + template: + spec: + restartPolicy: Never + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: renovate + image: ghcr.io/renovatebot/renovate:44.164.10 + # ENTRYPOINT(containerbase の初期化)は残して args だけ替える + args: [bash, /scripts/run.sh] + envFrom: + - configMapRef: + name: renovate-github + env: + - name: OWNER + value: danything + - name: RENOVATE_AUTODISCOVER_FILTER + value: danything/* + - name: APP_PRIVATE_KEY + valueFrom: + secretKeyRef: {name: renovate-secrets, key: github-app-private-key, optional: true} + resources: + requests: + cpu: 250m + memory: 1Gi + limits: + memory: 4Gi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ALL] + volumeMounts: + - name: scripts + mountPath: /scripts + - name: work + mountPath: /tmp/renovate + volumes: + - name: scripts + configMap: + name: renovate-scripts + # clone と postUpgradeTasks の作業場所(RENOVATE_BASE_DIR の既定)。毎回空から + - name: work + emptyDir: + sizeLimit: 10Gi +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: renovate-5ym + namespace: renovate +spec: + schedule: "7-59/15 * * * *" + concurrencyPolicy: Forbid + startingDeadlineSeconds: 600 + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + jobTemplate: + spec: + backoffLimit: 0 + activeDeadlineSeconds: 2700 + template: + spec: + restartPolicy: Never + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: renovate + image: ghcr.io/renovatebot/renovate:44.164.10 + args: [bash, /scripts/run.sh] + envFrom: + - configMapRef: + name: renovate-github + env: + - name: OWNER + value: 5ym + - name: RENOVATE_AUTODISCOVER_FILTER + value: 5ym/* + - name: APP_PRIVATE_KEY + valueFrom: + secretKeyRef: {name: renovate-secrets, key: github-app-private-key, optional: true} + resources: + requests: + cpu: 250m + memory: 1Gi + limits: + memory: 4Gi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ALL] + volumeMounts: + - name: scripts + mountPath: /scripts + - name: work + mountPath: /tmp/renovate + volumes: + - name: scripts + configMap: + name: renovate-scripts + - name: work + emptyDir: + sizeLimit: 10Gi +--- +# Forgejo(fj.doany.io)の doa。中身は doa/renovate の .forgejo/workflows/renovate.yml の env と同じ。 +# Pod から fj.doany.io へは IPv6 でしか届かない(IPv4 はヘアピンで落ちる。apps/forgejo/runner.yaml の冒頭) +apiVersion: batch/v1 +kind: CronJob +metadata: + name: renovate-forgejo + namespace: renovate +spec: + schedule: "12-59/15 * * * *" + concurrencyPolicy: Forbid + startingDeadlineSeconds: 600 + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + jobTemplate: + spec: + backoffLimit: 0 + activeDeadlineSeconds: 2700 + template: + spec: + restartPolicy: Never + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: renovate + image: ghcr.io/renovatebot/renovate:44.164.10 + args: [bash, /scripts/run.sh] + env: + - name: RENOVATE_PLATFORM + value: forgejo + - name: RENOVATE_ENDPOINT + value: https://fj.doany.io/api/v1 + # Forgejo のユーザー renovate のトークン(チーム bots = 全リポジトリに書き込み) + - name: RENOVATE_TOKEN + valueFrom: + secretKeyRef: {name: renovate-secrets, key: forgejo-token, optional: true} + - name: RENOVATE_GIT_AUTHOR + value: Renovate Bot + - name: RENOVATE_AUTODISCOVER + value: "true" + - name: RENOVATE_AUTODISCOVER_FILTER + value: doa/* + # github.com のリリースノートやタグを読むとき、無いと匿名の回数制限(60 回/時)に当たる。 + # 権限なしの GitHub のトークンでよい。無ければ空で動く + - name: GITHUB_COM_TOKEN + valueFrom: + secretKeyRef: {name: renovate-secrets, key: github-com-token, optional: true} + - name: LOG_LEVEL + value: info + resources: + requests: + cpu: 250m + memory: 1Gi + limits: + memory: 4Gi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ALL] + volumeMounts: + - name: scripts + mountPath: /scripts + - name: work + mountPath: /tmp/renovate + volumes: + - name: scripts + configMap: + name: renovate-scripts + - name: work + emptyDir: + sizeLimit: 10Gi diff --git a/pulumi/README.md b/pulumi/README.md index 555720f..a878215 100644 --- a/pulumi/README.md +++ b/pulumi/README.md @@ -115,7 +115,7 @@ apply 用は「自分が所有者のアプリ登録」しか書けない。所 止め(`skipArtifactsUpdate: true`)、代わりに Renovate の `postUpgradeTasks` が [renovate-post-upgrade.sh](renovate-post-upgrade.sh) を流す。Pulumi の CLI(`.pulumi-version`、公式のチェックサムと照らす)と bun(`.bun-version`)を入れて `pulumi install --no-plugins` し、作り直した bun.lock を同じ枝にコミットさせる。手元・CI と同じ `pulumi install` で作るので、CI の lock の確認とずれない。 - 実行の許可は 5ym/repo-config の renovate.yml の `RENOVATE_ALLOWED_COMMANDS`(2026-10-08。#306 の SDK の package.json の写しはやめた) + 実行の許可は [apps/renovate/renovate.yaml](../apps/renovate/renovate.yaml) の `RENOVATE_ALLOWED_COMMANDS`(2026-10-08。#306 の SDK の package.json の写しはやめた) - `*.doany.io` を家の 10.0.0.2 に向けているのは、exit ノード越しに家の外向きの IPv4 を引くと折り返しで届かないため。 `nb.doany.io` だけは外向きのアドレスで例外にしている。アドレスは書かず、2 段の名前 `nb.origin.doany.io` (ゾーンのワイルドカードに当たらず Cloudflare で引かれ、cloudflare-ddns が追従させる) に CNAME で向ける diff --git a/pulumi/renovate-post-upgrade.sh b/pulumi/renovate-post-upgrade.sh index 3963b69..ed5400b 100755 --- a/pulumi/renovate-post-upgrade.sh +++ b/pulumi/renovate-post-upgrade.sh @@ -5,9 +5,9 @@ # `file:sdks/netbird` で指していて、SDK は `pulumi install` でしか作れない(git には入れない。pulumi/README.md)。 # Renovate の `bun install` は SDK が無くて落ちるので、renovate.json でそれを止め(skipArtifactsUpdate: true)、ここで作る。 # -# 動くのは Renovate のコンテナ(ghcr.io/renovatebot/renovate、5ym/repo-config の renovate.yml)の中、リポジトリの直下。 +# 動くのは Renovate のコンテナ(ghcr.io/renovatebot/renovate、apps/renovate/renovate.yaml の CronJob)の中、リポジトリの直下。 # Pulumi の CLI は入っていないので、.pulumi-version の版を公式のチェックサムと照らしてから入れる。bun は containerbase の -# install-tool で .bun-version の版を入れる。許可は repo-config の renovate.yml の RENOVATE_ALLOWED_COMMANDS +# install-tool で .bun-version の版を入れる。許可は apps/renovate/renovate.yaml の RENOVATE_ALLOWED_COMMANDS set -euo pipefail cd "$(dirname "$0")" diff --git a/renovate.json b/renovate.json index d37624b..196bb26 100644 --- a/renovate.json +++ b/renovate.json @@ -63,7 +63,7 @@ ], "packageRules": [ { - "description": "pulumi/ の bun.lock は Renovate に作らせず、postUpgradeTasks の pulumi install で作る。package.json が NetBird の SDK を file:sdks/netbird で指していて、SDK は pulumi install でしか作れないので、Renovate 自身の bun install は落ちる (#304)。renovate-post-upgrade.sh が Pulumi の CLI と bun を入れて pulumi install し、作り直した bun.lock を同じ枝にコミットさせる。実行の許可は自前の Renovate (5ym/repo-config の renovate.yml) の RENOVATE_ALLOWED_COMMANDS。Pulumi.yaml の packages の版 (customManagers) を上げたときも同じく作り直す。 matchFileNames に bun.lock も入れる: bun の manager は bun.lock を package file として扱うので、package.json だけだと当たらず、Renovate 自身の bun install が走ってしまった (2026-10-08)。 **pulumi/ の更新は専用の枝 (renovate/pulumi) にまとめる**: skipArtifactsUpdate は、まとめた枝の全部の更新が指定しているときだけ効く (Renovate の docs)。renovate/all に tools/Dockerfile などと一緒に入ると効かず、postUpgradeTasks も走らなかった (#310)。", + "description": "pulumi/ の bun.lock は Renovate に作らせず、postUpgradeTasks の pulumi install で作る。package.json が NetBird の SDK を file:sdks/netbird で指していて、SDK は pulumi install でしか作れないので、Renovate 自身の bun install は落ちる (#304)。renovate-post-upgrade.sh が Pulumi の CLI と bun を入れて pulumi install し、作り直した bun.lock を同じ枝にコミットさせる。実行の許可は自前の Renovate (apps/renovate/renovate.yaml) の RENOVATE_ALLOWED_COMMANDS。Pulumi.yaml の packages の版 (customManagers) を上げたときも同じく作り直す。 matchFileNames に bun.lock も入れる: bun の manager は bun.lock を package file として扱うので、package.json だけだと当たらず、Renovate 自身の bun install が走ってしまった (2026-10-08)。 **pulumi/ の更新は専用の枝 (renovate/pulumi) にまとめる**: skipArtifactsUpdate は、まとめた枝の全部の更新が指定しているときだけ効く (Renovate の docs)。renovate/all に tools/Dockerfile などと一緒に入ると効かず、postUpgradeTasks も走らなかった (#310)。", "matchFileNames": [ "pulumi/package.json", "pulumi/bun.lock", @@ -84,7 +84,7 @@ } }, { - "description": "AdGuard Home の版上げ。起動時に設定を移行する (schema_version) ので、postUpgradeTasks の renovate-post-upgrade.sh が新しい版の --check-config で apps/adguardhome/config.yaml を移行し、deployment.yaml の doany.io/config-sha256 も合わせて同じ枝にコミットする。読めない設定ならスクリプトが落ちて PR に出る。実行の許可は自前の Renovate (5ym/repo-config の renovate.yml) の RENOVATE_ALLOWED_COMMANDS。専用の枝にするのは、移行が落ちたときに all dependencies の PR まで止めないため", + "description": "AdGuard Home の版上げ。起動時に設定を移行する (schema_version) ので、postUpgradeTasks の renovate-post-upgrade.sh が新しい版の --check-config で apps/adguardhome/config.yaml を移行し、deployment.yaml の doany.io/config-sha256 も合わせて同じ枝にコミットする。読めない設定ならスクリプトが落ちて PR に出る。実行の許可は自前の Renovate (apps/renovate/renovate.yaml) の RENOVATE_ALLOWED_COMMANDS。専用の枝にするのは、移行が落ちたときに all dependencies の PR まで止めないため", "matchDatasources": [ "docker" ],