#10 「githubのプライベートレポジトリをsubmoduleに追加すると困る件の話」

@acidlemonです。こんばんは。

tech.kayac.comアドベントカレンダーも気がついたら10日目ということで私の出番です。なんでこの日を選んだかっていうと今日はぼくの誕生日〜。ウィッシュリスト等はございませんので心の隅っこでおめでとうと唱えていただければと思います。ちなみにぼくがカヤックに入社する1ヶ月前まで在籍してたsugyanさんと年まで含めて生年月日がおなじらしいです。

さて! 何を書こうかなと思ったんですが、テーマが「私のイノベーション2013」みたいな感じだったはずなので今年の仕事を振り返ってみると…

  • 1月〜3月: 普通に仕事してた
  • 4月上旬: 社内ISUCONしてた
  • 4月下旬〜8月下旬: 普通に仕事してた
  • 9月〜11月上旬: ISUCON3の予選/本戦の準備してた
  • 11月下旬〜: 普通に仕事してた

実はISUCON以外とくに面白いことをやってないのでは…?

まぁそんなわけなので、「今年一年Appleさんからリジェクトされたまとめ」でも書こうかなーと思ったんですが、ちゃんとまとめてたわけでもないのでひとまず昨日困って頭を絞って解決した件でも書こうとおもいます。

gitのsubmoduleに認証が必要なrepoを追加する

最近ぼくは社内でみんながコピペするコードを精力的にうまいことまとめて共用パッケージにしてgitのsubmoduleで各プロジェクトに追加するとコピペしなくても大丈夫だよ! みたいなお節介活動をやっています。 なんじゃそれって人は秋のエンジニアぶつかり稽古2013@hisaichi5518が発表してきた資料をご覧いただければとおもいます。がんばってひさいち君のコピペだるいツイートを収集してこのお節介活動のスタートにこぎつけました。

さて、そんなわけでGithubのプライベートリポジトリにその共用パッケージを突っ込むところまではできたのですが、submoduleとして追加してJenkinsでCIしようとしたら大きな落とし穴が!

たいていJenkinsとGithubのプライベートリポジトリを組み合わせるときはJenkins用に作ったSSHの公開鍵をGithubでDeploy Keyに指定してクローン出来るようにします。しかし、githubの仕様でDeploy Keyは1つの鍵は1個のリポジトリにしか指定できません。

ということは…submoduleを引っ張ってくるには別のDeploy Keyを指定しないとなりません。やだ! それはやだ! というかだいぶめんどくさいです。

sshの接続先を使い分ける

Deploy Keyでなんとかするアプローチでやる場合は、メインリポジトリとsubmoduleがおいてあるのはどちらもGithubなので、~/.ssh/config に2つの鍵使い分け設定を書かなければなりません。それをやりたいのであれば以下のURLが参考になります。

最初これやるかなーと思ったんですが、CI回す環境はともかく、このリポジトリを使う全員にこの設定を強制するのはさすがに現実的ではない感じです。ぼくはこういうトリッキーなことをやらなきゃならない時にホントにそれを採用するかどうかは「新しくプロジェクトに入ってきた人にトリッキーな仕組みを説明したときに恥ずかしくないか(胸を張って説明できるか)」で決めているので、その基準だとこのアイディアはボツにしました。

httpsでURLにユーザ名とパスワードを入れる

とはいえなんらかの手を打たないとなりません。新しく入ってきた人に特殊な設定をやらせない方法を考えてみましたが、sshと公開鍵を使っているうちはどうにもならないかなという感じです。であればsubmoduleをsshじゃない方法で追加するしかありませんね。ということでhttpで追加します。実際にやってみた例として、以下のURLが参考になります。

なるほど! git submodule add https://username:password@github.com とやるわけですね! とりあえずダミーユーザを作ってなんとかする感じになるでしょうか。

でも記事に書いてあるとおり .gitmodules にユーザ名とパスワードがでちゃう! これはちょっとかっこ悪い気がしますねー。あんまり胸張って説明できない感じです。何より誰かがそのユーザ名とパスワードを使ってログインしたらそのアカウントでいろいろできてしまいますからね。

httpsでURLにOAuth Tokenを入れる

ということでやっと本題! 途方に暮れてGithubのヘルプとかブログとかを眺めてみたらこんなものがありました。

これだ! OAuth Tokenをつかって git submodule add https://<token>@github.com とやるわけです。ユーザ名とパスワードを生で書くのと何が違うんだコラって言われると気休め程度の効果しかない気もしないわけではないですが、OAuth TokenであればScopeをある程度絞ることができるので、username/passwordがボンと書いてあるよりは出来ることを絞ることができます。

ただ、自分のアカウントでOAuth Tokenを吐き出してそれをsubmoduleのURLに入れてしまうとそれを見た人みんなが自分になりすまし放題になってしまいますので、やっぱりダミーユーザみたいなのは作った方が無難です。こればっかりはしかたない…。

なお、このOAuth Tokenはcurlでガシガシ叩かなくてもGithubのAccount SettingのApplicationsのところからPersonal Access Tokensをポチポチすることで作ることができます。OAuthよくわからんみたいな人でもポチポチやって40桁の英数字をゲットしてhttpsのURLにつっこめばとりあえずcloneできるURLを作れます。

ちなみにハマリどころが1点あるので注意です。GithubのBlogには

git clone https://<token>@github.com/owner/repo.git

or

git clone https://<token>:x-oauth-basic@github.com/owner/repo.git

でcloneできるよと書いてあります。前者はパスワードを省略してユーザ名だけでアクセスするパターンなのですが、gitのバージョンが古めだとこの記法だとBasic認証のパスワードを尋ねるプロンプトがでてしまって自動化できなくなってしまいます。なので、git 1.7台が存在するような環境では後者のようにパスワード部分にx-oauth-basicと入れたスタイルでgit submodule addしたほうが無難です。


さていかがでしたでしょうか? 明日は @fujiwara の登場です。椅子などを用意しておまちください。