GitHubで管理しているリポジトリの移譲先の調べ方を考えてみた

サービスグループの武田です。複数のリポジトリを段階的に移譲してく必要があり、ローカルリポジトリの参照先URLを変更する前に、リポジトリが移譲されたのか。されていた場合は変更後のURLはどこなのか。を取得する方法を考えてみました。
2020.04.20

こんにちは。サービスグループの武田です。

GitHubを利用してリポジトリ管理をしている場合、そのリポジトリのオーナーを変更できます。機能としては リポジトリの移譲 として提供されています。

リポジトリを移譲する - GitHub ヘルプ

普段使用している分には移譲されたかどうかは気にする必要はありません。ブラウザからアクセスすると自動でリダイレクトされますし、git cloneなどコマンドで操作する際にも特に意識することなく動作するためです。とはいえ、自分たちで管理しているリポジトリを移譲したら、ローカルリポジトリの参照先などは変更後のURLに変えておきたいですよね。

そんなわけで、今回はリポジトリが移譲されたのか。されていた場合は変更後のURLはどこなのか。を取得する方法を考えてみました。

環境

次のような環境で検証しています。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.4
BuildVersion:	19E287

$ curl --version
curl 7.64.1 (x86_64-apple-darwin19.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.39.2
Release-Date: 2019-03-27
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS GSS-API HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM NTLM_WB SPNEGO SSL UnixSockets

パブリックリポジトリ

まずはパブリックリポジトリから考えてみます。

ブラウザでアクセスしてみる

一番簡単なのはブラウザを起動してアクセスしてみることです。一例としてhttps://github.com/defunkt/hubにアクセスしてみるとhttps://github.com/github/hubにリダイレクトされます。簡単ですね。

curlコマンドでURLをたたいてみる

GUIではなくCUIで調べたい!という方もいますよね。わかります。上記と同じURLにcurlでアクセスしてみましょう。

$ curl https://github.com/defunkt/hub -o /dev/null -D - -s
HTTP/1.1 301 Moved Permanently
date: Mon, 20 Apr 2020 00:00:00 GMT
content-type: text/html; charset=utf-8
server: GitHub.com
status: 301 Moved Permanently
vary: X-PJAX, Accept-Encoding, Accept, X-Requested-With
location: https://github.com/github/hub
cache-control: no-cache
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
expect-ct: max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"
content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; connect-src 'self' uploads.github.com www.githubstatus.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events wss://live.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; frame-src render.githubusercontent.com; img-src 'self' data: github.githubassets.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; manifest-src 'self'; media-src 'none'; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com
Content-Length: 95

ステータスコードとlocationヘッダで確認できますね。情報量が多いという場合は-wオプションで絞ることもできます。

$ curl https://github.com/defunkt/hub -o /dev/null -s -w '%{http_code}\n%{redirect_url}\n'
301
https://github.com/github/hub

GitHub APIをたたいてみる

CUIで確認するもうひとつの方法としてGitHub APIの利用が考えられます。実際にたたいてみましょう。

$ curl https://api.github.com/repos/defunkt/hub
{
  "message": "Moved Permanently",
  "url": "https://api.github.com/repositories/401025",
  "documentation_url": "https://developer.github.com/v3/#http-redirects"
}

移譲されていないリポジトリの場合は、リポジトリの情報が大量に取得できるのですが、移譲されている場合はシンプルな結果が取得できます。urlフィールドのエンドポイントを追加でたたいてみます(結果が長いので一部だけ取り出します)。

$ curl https://api.github.com/repositories/401025 -s | jq -r '.html_url'
https://github.com/github/hub

まさしく欲しかったURLが取得できました。

プライベートリポジトリ

パブリックリポジトリの場合は比較的容易に調べられました。ではプライベートリポジトリではどうでしょうか。GUIでよければ、GitHubにログインした状態でアクセスしてみれば大丈夫です。問題はCUIです。

curlで普通にリポジトリのURLをたたいても 404 になります。認証していないのでしかたないです。ということでアクセストークンを利用することになります *1。トークンの作成については次のドキュメントを参考にしてください。

コマンドライン用の個人アクセストークンを作成する - GitHub ヘルプ

GitHub APIをたたいてみる

ヘッダにトークンを追加するだけで、基本的にはパブリックリポジトリの場合と同じです(リポジトリ名などは架空です)。

$ curl -H 'Authorization: token xxx' https://api.github.com/repos/TAKEDA-Takashi/private-repo -o /dev/null -s -w '%{http_code}\n%{redirect_url}\n'
301
https://api.github.com/repositories/123456789

$ curl https://api.github.com/repositories/123456789 -s | jq -r '.html_url'
https://github.com/TAKEDA-Takashi2/private-repo

シンプルに取得できましたね。

GraphQLを使ってみる

せっかくアクセストークンを作成したので、おまけでGraphQLを使ってみました。GraphQLを使用するためにはパブリックリポジトリであっても認証が必要です。JSON内の文字列では改行できませんが、見やすくするためtrを使って強引に整形しています(一行で書く場合は不要です)。

$ curl -H 'Authorization: token xxx' -X POST -d "$(echo '
{
  "query": "query {
    repository(owner:\"defunkt\", name:\"hub\") {
      url,
      sshUrl
    }
  }"
}
' | tr -d '\n')" https://api.github.com/graphql

{"data":{"repository":{"url":"https://github.com/github/hub","sshUrl":"git@github.com:github/hub.git"}}}

GraphQLを使うと直接移譲後のURLが取得できるんですね。なるほど。

まとめ

複数のリポジトリを段階的に移譲してく必要があり、ローカルリポジトリの参照先URLを変更する事前チェックの方法として考えてみました。誰かの助けになれば幸いです。

脚注

  1. ベーシック認証での認証も可能ですが推奨されません