Private な gem を参照しているリポジトリに Renovate を入れる

tl;dr
- Gemfile での git リポジトリのURL は
https://
とする- SSH プロトコルの場合は Token による認証が行えないため
- Renovate cloud は SSH での認証には対応してなさそう
- renovate.json の
hostRules
で以下のように credential を設定するrenovate.json (抜粋){ "matchHost": "github.com", "hostType": "rubygems", "username": "x-access-token", "password": "{{ secrets.GITHUB_TOKEN }}" }
-
username
はx-access-token
とする -
password
に PAT をセットする ( 直接記述するのではなく secrets 参照を利用する )
-

Renovate のインストール

Private な gem の更新でエラーになっている
管理画面でjobを確認
想定どおり private な gem を参照してるあたりでエラーが出てる
Retrying `git clone --bare --no-hardlinks --quiet --no-tags --depth 1 --single-branch -- git@github.com:snaka/rubocop-rails-omakase /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100` due to error (2/4): Bundler::Source::Git::GitCommandError Git error: command `git clone --bare --no-hardlinks --quiet --no-tags --single-branch -- git@github.com:snaka/rubocop-rails-omakase /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100` in directory /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100 has failed.
Host key verification failed.\r
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Retrying without --depth argument.
Retrying `git clone --bare --no-hardlinks --quiet --no-tags --depth 1 --single-branch -- git@github.com:snaka/rubocop-rails-omakase /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100` due to error (3/4): Bundler::Source::Git::GitCommandError Git error: command `git clone --bare --no-hardlinks --quiet --no-tags --single-branch -- git@github.com:snaka/rubocop-rails-omakase /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100` in directory /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100 has failed.
Host key verification failed.\r
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Retrying `git clone --bare --no-hardlinks --quiet --no-tags --depth 1 --single-branch -- git@github.com:snaka/rubocop-rails-omakase /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100` due to error (4/4): Bundler::Source::Git::GitCommandError Git error: command `git clone --bare --no-hardlinks --quiet --no-tags --single-branch -- git@github.com:snaka/rubocop-rails-omakase /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100` in directory /tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100 has failed.
Host key verification failed.\r
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Git error: command `git clone --bare --no-hardlinks --quiet --no-tags
--single-branch -- git@github.com:snaka/rubocop-rails-omakase
/tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100`
in directory
/tmp/renovate/cache/others/bundler/cache/bundler/git/rubocop-rails-omakase-82b8627c78d94b5be177c7de6a29cc2c39d63100
has failed.
Host key verification failed.\r
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.

-
hostRules
で host ごとの credential を設定できる-
matchHost
- ex.
https://hoge.example.com
- ex.
-
token
orusername
/password
-
hostType
- platform:
github
,azure
, etc - datasource:
npm
,maven
,github-tags
, etc
- platform:
-
疑問
Renovate から GitHub API を通してのアクセスと、パッケージマネージャからの Git プロトコルを利用したアクセスの両方を考慮する必要がある?
("Example fro gomod" から引用)
{
"matchHost": "https://github.com/some-org",
"token": "ghp_token_for_different_org",
"hostType": "go"
},
{
"matchHost": "https://api.github.com/repos/some-org",
"token": "ghp_token_for_different_org",
"hostType": "github"
}

Importantly, such package managers are run via shell commands and do not understand Renovate's hostRules objects, so Renovate needs to reformat the credentials into formats (such as environment variables or configuration files) which the package manager understands.
https://docs.renovatebot.com/getting-started/private-packages/#package-manager-credentials-for-artifact-updating
パッケージマネージャは hostRule
を理解できないので、それが理解できる形式(環境変数や config など)に Renovate が変換しているらしい
たとえば bundler
の場合、 hostType
に rubygems
と記述されていたら、それを Bundler が参照する環境変数にセットしてくれてるらしい

Mend cloud App での secrets の設定
Web UI で設定できる
hostRules
の設定

matchHost
に private リポジトリを識別するURLの一部を設定してみる
{
"matchHost": "git@github.com:snaka",
"hostType": "rubygems",
"token": "{{ secrets.GITHUB_TOKEN }}"
}
... が、Renovate に怒られた
hostRules matchHost `https://**redacted**@github.com:snaka` is not a valid URL.
Error: config-validation\n at mergeRenovateConfig (/usr/local/renovate/lib/workers/repository/init/merge.ts:200:19)\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at getRepoConfig (/usr/local/renovate/lib/workers/repository/init/config.ts:14:12)\n at initRepo (/usr/local/renovate/lib/workers/repository/init/index.ts:56:12)\n at Object.renovateRepository (/usr/local/renovate/lib/workers/repository/index.ts:64:14)\n at attributes.repository (/usr/local/renovate/lib/workers/global/index.ts:206:11)\n at start (/usr/local/renovate/lib/workers/global/index.ts:191:7)\n at /usr/local/renovate/lib/renovate.ts:19:22

matchHost
の使われ方

bundler lock
コマンドに credential を渡す方法を探す
bundler config --local
で credential をセットしていそう
bundlerHostRulesAUthCommands
は resolvedHost
に -
が含まれる場合に認証情報を追加している?
spec 見る限り bundler 2 以上の場合は環境変数に認証情報がセットされていそう?

bundler の credential 設定方法を確認する
基本は
bundle config set --global SOURCE_HOSTNAME USERNAME:PASSWORD
URL ごとに指定する場合は
bundle config set --global https://github.com/rubygems/rubygems.git username:password
環境変数を使う場合
export BUNDLE_GITHUB__COM=username:password
OAuth token を環境変数で利用する場合
export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic

Renovate でその環境変数名を組み立てていると思われる箇所
-
resolvedHost
を.
で分離 (github.com
⇒github
,com
) - 分離されたそれぞれの文字列を大文字に
-
github
⇒GITHUB
-
com
⇒COM
-
-
__
で結合し直して、prefix としてBUNDLE_
を付与するBUNDLE_GITHUB__COM

xxxx:x-oauth-basic
はすでに非推奨かもしれない
https://x-access-token:TOKEN@github.com
形式になった?
以下の hostRule で試してみる
{
"matchHost": "github.com",
"hostType": "rubygems",
"username": "x-access-token",
"password": "{{ secrets.GITHUB_TOKEN }}"
}
... が、エラーは変わらず。一応環境変数へはセットされているように見えた
"env": {
"BUNDLE_GITHUB__COM": "x-access-token:**redacted**",

x-access-token
と PAT を使って git リポジトリにアクセスを試す
普通にアクセスできた
$ git clone https://github.com/snaka/rubocop-rails-omakase.git
Cloning into 'rubocop-rails-omakase'...
Username for 'https://github.com': x-access-token
Password for 'https://x-access-token@github.com':
remote: Enumerating objects: 57, done.
remote: Counting objects: 100% (57/57), done.
remote: Compressing objects: 100% (38/38), done.
remote: Total 57 (delta 18), reused 57 (delta 18), pack-reused 0 (from 0)
Receiving objects: 100% (57/57), 21.02 KiB | 5.25 MiB/s, done.
Resolving deltas: 100% (18/18), done.

https://
に変更してみる
Gemfile に記載されている URL を gem "rubocop-rails-omakase", require: false, git: "git@github.com:snaka/rubocop-rails-omakase"
SSH プロトコルなので PAT による認証が行われていない可能性がある
- gem "rubocop-rails-omakase", require: false, git: "git@github.com:snaka/rubocop-rails-omakase"
+ gem "rubocop-rails-omakase", require: false, git: "https://github.com/snaka/rubocop-rails-omakase"
これで、 PAT を使ったプライベートリポジトリのアクセスが通るようになった

GitHub で Renovate で利用するための PAT を発行する
以下のように、対象リポジトリに対する code の参照権限を与えておく

Renovate cloud で実行する場合に環境変数を参照して bundler の挙動を変える
Gemfile で git_source
の挙動を切り替えている部分がある
意図としては private のリポジトリを参照するときは ssh プロトコルを利用したい
git_source(:github) do |repo|
if repo.start_with?("snaka/")
"git@github.com:#{repo}"
else
"https://github.com/#{repo}.git"
end
end
しかし、 Renovate で実行する場合はそこの挙動をスキップして https でのアクセスに切り替えたい。

BUNDLE_GITHUB__COM
が設定済みの場合は private リポジトリに https でアクセス可能なので
以下の修正で対応できた
git_source(:github) do |repo|
- if repo.start_with?("snaka/")
+ if repo.start_with?("snaka/") && !ENV.has_key?("BUNDLE_GITHUB__COM")
"git@github.com:#{repo}"
else
"https://github.com/#{repo}.git"