Cloud Source Repositoriesのリポジトリ変更をCloud Pub/Subで受け取る


GCPにはデフォルトでGitリポジトリが提供されています。
https://cloud.google.com/source-repositories/

## Cloud Source Repositoriesとは？

GitHubとか使えないけどプライベートリポジトリが使いたい、プルリクとかでレビューもしなくてもいいしMarkdownのプレビュー見れなくてもいいからサクッとGitリポジトリ作りたいって方は便利かもしれません。

Developer Consoleでは開発、Developmentとかってメニューになってるはずです。

![スクリーンショット 2016-09-22 16.27.19.png](https://qiita-image-store.s3.amazonaws.com/0/8637/b0d796de-5ce8-3584-184f-06ce0fc83025.png "スクリーンショット 2016-09-22 16.27.19.png")


最大1GBまで使えます。
わりと便利です。

まだベータらしいです。
なのでフリーで使えます。

ちなみにこの1GBはプロジェクト全体で1GBなのか、リポジトリで1GBなのかはよくわかってません。
1GBまで使うことがないので限界が分かりません。
知ってる方いたら教えてください。

### リポジトリ

1プロジェクトで複数のリポジトリが作れます。
制限は…わからない。

### エディタ

Developer Consoleを使ってブラウザ上でソースコードの編集ができます。
どうもこのソースコードの画面、[Cloud Datalab](https://cloud.google.com/datalab/)っぽいです。
コミット時のヘルプリンクが[Datalabのページ](https://cloud.google.com/datalab/docs/how-to/migrating?hl=en_US&_ga=1.115119439.999579677.1469021022)になってた。

Cloud Datalabをちゃんと使ったことないので全然気付きませんでした。

## Cloud Pub/Sub

実は、リポジトリを作ると勝手にCloud Pub/Subのトピックを勝手に作ってくれます。

`projects/PROJECT_ID/topics/repository-changes.REPOSITORY_NAME`というトピックができます。

読んで字の如く、リポジトリ変更のフックですね。
普通のGitHookと同じ。

ちなみに、これに関する公式ドキュメントはどこにもありません！
2016年9月時点では、おそらくこのQiita記事だけが唯一のドキュメントですｗ

調べようと思ったんですが、それぞれ一般的な名称過ぎてググラビリティが低くて発見には至ってません。
たぶんレア機能だからまとめてる人もいないんだと思う…。

### 発生するイベント

プルリクとかないので、僕が自分でリポジトリ操作してみて観測できた範囲でリストアップしてみます。

- push
	- ソースコードがPushされると発生します
- alias_changed
	- pushとセットで発生するみたい。
	- 詳細はよく分かってない。
- workspace_changed
	- 前述のエディタ画面ですが、コミットするまでの間、ワークスペースとして変更通知をしてくれます。
	- ファイルを保存する度に起きてるっぽいです。
	- ワークスペースでコミットすればpushとalias_changedが発生します。

### メッセージ

`data`と`attributes`にリポジトリの変更イベントの情報が入ってます。
どうも差分とかそういう詳細なのは取れないっぽいです。

#### push

```data
{ repo_link: 'リポジトリのURL',
  repo_id: 'リポジトリID(たぶんコンソールから見れない)',
  project_id: 'プロジェクトID',
  repo_name: 'リポジトリ名',
  timestamp: 'イベントが発生した時間(UTC)',
  push: 
   { revision_count: 1, ←よくわかってない
     pusher: 'pushした人(GCPの認証ユーザーだと思う。)',
     revision_ids: [ 'pushした時のコミットID' ],
     alias_changes: [ [Object] ] } } ←なんか入ってるっぽい
```

```attributes
{ 'source.developers.google.com/name': 'リポジトリ名',
  'source.developers.google.com/project': 'プロジェクトID',
  'source.developers.google.com/repo': 'リポジトリ名',
  'source.developers.google.com/type': 'push' }
```

#### alias_changed

```data
{ repo_link: 'リポジトリのURL',
  repo_id: 'リポジトリID(たぶんコンソールから見れない)',
  project_id: 'プロジェクトID',
  repo_name: 'リポジトリ名',
  timestamp: 'イベントが発生した時間(UTC)',
  alias_changed: 
   { alias: 'refs/heads/ブランチ名',
     kind: 'MOVABLE',
     old_revision_id: '前のコミットID',
     new_revision_id: '今のコミットID' } }
```

```attributes
{ 'source.developers.google.com/alias': 'refs/heads/master',
  'source.developers.google.com/name': 'refs/heads/master',
  'source.developers.google.com/project': 'プロジェクトID',
  'source.developers.google.com/repo': 'リポジトリ名',
  'source.developers.google.com/type': 'alias_changed' }
```

`alias_changed.kind`ってあるから、なんか他にも種類があるのかも。

#### workspace_changed

```data
{ repo_link: 'リポジトリのURL',
  repo_id: 'リポジトリID(たぶんコンソールから見れない)',
  project_id: 'プロジェクトID',
  repo_name: 'リポジトリ名',
  timestamp: 'イベントが発生した時間(UTC)' }

```

```attributes
{ 'source.developers.google.com/alias': 'master',
  'source.developers.google.com/name': 'acropolis__作業してたGCPユーザー__作業してたブランチ',
  'source.developers.google.com/project': 'プロジェクトID',
  'source.developers.google.com/repo': 'リポジトリ名',
  'source.developers.google.com/type': 'workspace_changed',
  'source.developers.google.com/workspace': 'acropolis__作業してたGCPユーザー__作業してたブランチ' }
```

### 注意

- リポジトリを消してもPub/Subのトピックは消えないので、自分で消しましょう。
- トピックを消してしまうとたぶん復活できないです。
	- 同じトピック名で作ればいける気はする
- リポジトリはタダだけど、Pub/Subは有料です。
	- まあお手軽リポジトリだろうから、Pub/Subでめっちゃ課金されるほどメッセージやりとり発生しないと思いますけどね。
- このメッセージの内容は2016年9月時点のものです。
	- 今後拡充して詳しいメッセージ付けてくれるようになるかもしれないし、送ってこなくなるかもしれません。

## 何に使えるのか

PushされたときのHookなので可能性は無限大…。
ではあるんですが、Subをがんばって作らないといけないですね。
そこは普通にCloud Pub/SubのSubscriberになるので、何で作ってもいいですね。
何で作っても良いから何でもできるね…。

まあでもガッツリ使う物でもないので、僕はGCEインスタンスの設定とかをここで管理して、最新に同期するってことくらいにしか使ってないです。

そもそも大した情報送ってこないし。

## サンプル

メッセージ確認するときのnodeのクソサンプル貼っときますね。
ちゃんとしたコードはpub/subの記事を探した方が良いと思うよ。

```
var gcloud = require('gcloud');
var pubsub = gcloud.pubsub({
  projectId: 'プロジェクト',
  keyFilename: 'JSONファイル'
});

var topic = pubsub.topic('repository-changes.リポジトリ名');
var options = {
  interval: 1,
  autoAck: true
}

topic.subscribe('サブスクリプション名', options, function(err, subscription, apiResponse) {
  var count = 0;
  function onError(err) {
    console.log("えらーだよ");
    console.log(err);
  }
  function onMessage(message) {
    if (message.attributes['source.developers.google.com/type'] == 'push') {
      console.log("きたよ、ログが！" + count++);
      console.log(message.data);
      console.log(message.attributes);
    }
  }
  subscription.on('error', onError);
  subscription.on('message', onMessage);
  console.log("待ってるよ");
});

```

## 結論

pushされたことはわかるので、それを受けてソースコード同期するとかには使えそうですね。