{"action":"created","comment":{"url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/comments/114097643","pull_request_review_id":35538626,"id":114097643,"diff_hunk":"@@ -0,0 +1,358 @@\n+---\n+title: E2E テストを CircleCI 2.0 (Beta) で完結させてみた話\n+date: 2017-05-08 00:00 JST\n+authors: ff_koshigoe\n+tags: test\n+---\n+\n+こんにちは、あっという間に社内勉強会の順番がやってきそうでフルえているコシゴエです。気がついたら二年近く会社ブログを書いていませんでした…。\n+\n+最近、ようやく重い腰を上げて Docker と CircleCI 2.0 を使い始めたので、E2E テストでの活用を試みている話をしたいと思います。\n+\n+<!--more-->\n+\n+はじめに\n+----\n+\n+突然ですが、弊社プロダクト [dfplus.io](https://dfplus.io/) では、[TestCafe](https://testcafe.devexpress.com/) を使用して E2E テストを自動化しています。\n+\n+dfplus.io は、異なるリポジトリで管理しているフロントエンド(JS)とバックエンド(Ruby)から構成され、E2E テストはフロントエンドのリポジトリで管理しています。E2E テストはリポジトリへの push をトリガーに [CircleCI](https://circleci.com/) で実行し、このときのバックエンドは E2E 用に用意した共用環境(Heroku 環境)を利用しています。\n+\n+E2E テストをしばらく運用した結果、いくつかの課題が見えてきました。今回は、その課題を [CircleCI 2.0 Beta](https://circleci.com/beta-access/) を利用して解決を試みた取り組みについて紹介します。\n+\n+\n+現在 E2E テストで抱えている問題\n+----\n+\n+dfplus.io では、E2E テストの自動化を始めて間もなく、十分な知見があるとは言えない状況です。プロダクト開発チームが本質的な問題に集中できる様に、E2E テスト自動化に取り組む時間を捻出して手探りながらも着実に改善を進めていますが、いくつか目に見える問題を抱えています。\n+\n+- 共用バックエンドの状態に依存するため思わぬところでテストが通らない(20 分待たされたあげくに…)\n+- E2E テストに時間がかかりすぎる(push の度に 20 分以上待たされる事も…)\n+- E2E テスト実行スクリプトの今の実装上、対象テストケースを分割した並行実行が行えない(並行実行すれば時間短縮は可能)\n+- バックエンド実行環境が E2E 実行環境から離れた場所にあり DB アクセス権がない(テストデータセットアップのトリガーが…)\n+\n+\n+問題解決のアイデア\n+----\n+\n+まず、バックエンドが共用である点と、バックエンドが E2E 実行環境から隔離された環境で動いている点について考えます。\n+\n+CircleCI 2.0 では任意の Docker イメージから作った任意の数のコンテナを動かす事ができるので、各 E2E テスト専用のバックエンドをオンデマンドに動かす事ができます。このバックエンドは E2E テスト実行環境から直接触る事ができる場所で動くため、必要なテストデータを自由にセットアップさせる事もできます。\n+\n+※ CircleCI 1.0 でも Docker を上手く使えるのかもしれませんが、元々 CircleCI に詳しくなかったため、Docker により近づいた印象を(勝手に)受けた 2.0 を使う事にします。\n+\n+\n+前提知識：CircleCI 2.0 のさわり\n+----\n+\n+前提知識として簡単に CircleCI 2.0 について説明しようと思いましたが、ドキュメントに言語ごとの[チュートリアル](https://circleci.com/docs/2.0/language-ruby/)が用意されているので CircleCI 2.0 をご存じない方はざっと目を通すと概要をつかめると思います。\n+\n+CircleCI 2.0 では、一度のジョブで行われる一連の流れのほぼ全てを設定ファイル `.circleci/config.yml` に記述する必要があります。CircleCI 1.0 はおおよその流れが決まっていて、適宜オーバーライドする形式なので `circle.yml` に数行書く程度で実行出来ました。1.0 と比べて 2.0 は非常に面倒だと思う方が多いかもしれません。反面、任意のファイルを任意の処理位置でキャッシュし、次回以降のジョブで使い回す事ができるといった面に魅力を感じる方も多いと思います。\n+\n+また、ジョブを実行する環境として、2.0 では [Docker イメージか今まで同様の VM (Machine) が利用できます](https://circleci.com/docs/2.0/executor-types/)。Docker イメージを使えば、ジョブの実行環境をあらかじめ用意しておく事もできます。[CircleCI から提供されている Docker イメージ](https://circleci.com/docs/2.0/circleci-images/)もあるので、必要に応じて使い分けると良いでしょう。ちなみに、TestCafe を用いた E2E テストにおいては、必要となるものが多いため、CircleCI 提供のイメージをベースとする事をおすすめします。\n+\n+なお、 `circle.yml` よりも `.circleci/config.yml` が優先されるので、いつでも 1.0 に戻れる様に `circle.yml` を 1.0 の内容で残しておくと良いかもしれません。\n+\n+※ 真面目に計測していないので正確なデータは出せないのですが、ホストとなるマシンの性能かジョブの隠れたオーバーヘッドが取り除かれるのか、1.0 よりも 2.0 の方がトータルで速いと実感しています。キャッシュが使いやすいからかもしれません。\n+\n+### 例：node_modules ディレクトリのリストアとキャッシュ\n+\n+```yaml\n+# バージョン番号\n+version: 2\n+# 任意個のジョブを記述できる(一度に一つのジョブを実行)\n+jobs:\n+  # build という名前のジョブがデフォルトで実行される\n+  build:\n+    # ジョブの実行環境に Docker を使う\n+    docker:\n+      # 一つ目が primary container となり、steps 以下で記述されるコマンドを実行する環境となる\n+      - image: circleci/node:6.10.2-browsers\n+      # ポートを EXPOSE している場合、primary container の localhost からフォワードできる様になっている\n+      # `localhost:6379` で Redis サーバに接続可能\n+      - image: redis\n+    ..\n+    # ジョブで行う事は steps 以下に記述する\n+    steps:\n+      ...\n+      # キーに前方一致するキャッシュがあれば元のパスに復元してくれる\n+      # Rebuild without cache ボタンではこの手順がスキップされるだけでキャッシュ自体は消えない\n+      # 手軽にキャッシュを無かった事にしたい場合に備え、以下の様に環境変数を含めるという先人の知恵に習っている\n+      # http://engineer.crowdworks.jp/entry/2017/04/04/202719\n+      - restore_cache:\n+          name: Restore cache\n+          keys:\n+            - yarn-{{ .Environment.CACHE_KEY }}-{{ checksum \"yarn.lock\" }}\n+            - yarn-{{ .Environment.CACHE_KEY }}-\n+      - run:\n+          name: Install npm packages\n+          command: yarn install --prefer-offline\n+      - save_cache:\n+          name: Save cache\n+          key: yarn-{{ .Environment.CACHE_KEY }}-{{ checksum \"yarn.lock\" }}\n+          paths:\n+            - ~/.cache/yarn\n+            - ~/app/node_modules\n+      ...\n+```\n+\n+\n+バックエンドのコンテナ化\n+----\n+\n+まず大前提として、dfplus.io はコンテナを使った本番運用を行っていません。昔ながらの心温まる EC2(CLB) と [Auto Scaling](https://aws.amazon.com/jp/autoscaling/) で運用しています。今回は、あくまで E2E テストにおけるコンテナ利用のみを考えます。ざっくりと、以下の方針で粛々と作業を進めました。詳細な内容は、Rails をコンテナで動かすという特筆することのない単純なものなので割愛します。\n+\n+- Alpine Linux を使う\n+- アプリケーションのソースコードをコンテナに含める\n+- アプリケーションが依存するパッケージ類(gem など)もコンテナに含める\n+- アプリケーションが依存するミドルウェアもそれぞれコンテナにする\n+- レジストリは Amazon ECR を利用する\n+\n+### 余談：Docker イメージの自動ビルド\n+\n+ちなみに、バックエンドのコンテナ化作業は CircleCI 2.0 を使い始める前に進めていたため、イメージの自動ビルドには [AWS CodePipeline](https://aws.amazon.com/jp/codepipeline/) ([AWS CodeBuild](https://aws.amazon.com/jp/codebuild/)) を使っています。CodePipeline 設定作業の一連で作った CodeBuild で設定した環境変数を AWS の管理画面から変更できないのが不満ですが、とても簡単に実現できました。\n+また、GitHub リポジトリへの push をフックに CodePipeline を起動していますが、CodeBuild には S3 経由で zip ファイルが渡ります。この影響で、リポジトリで管理している実行ファイルの実行権限は消える様です。\n+\n+なお、近々 CircleCI 2.0 に移るかもしれません。\n+\n+\n+CircleCI 2.0 で Docker コンテナを動かす\n+----\n+\n+パブリックレジストリにある Docker イメージを使う場合、設定の `jobs: > {job name}: > docker: > {i}: > image:` でイメージを指定するだけで済みます。一方、 `jobs: > {job name}: > docker: > {i}: > image:` にはプライベートレジストリのイメージは指定できません。自分で認証(`docker login`)を通した上で、適宜イメージを取得(`docker image pull` など)する必要があります。\n+\n+さらに、CircleCI 2.0 で docker コマンドを実行するためには、[Remote Docker Environment](https://circleci.com/docs/2.0/building-docker-images/) と呼ばれる隔離環境を立ち上げて使用する必要があります。これは steps: 以下に `setup_remote\\docker` を記述するだけで準備出来ます。\n+\n+また、Remote Docker Environment で動くコンテナは、primary container とは異なるネットワークに所属します。primary container から Remote Docker Environment で動くコンテナへの直接的なネットワーク通信は行えません。[通信したいコンテナが属するネットワークに参加する形で新しくコンテナを作り、その新しく作ったコンテナから通信する必要があります](https://circleci.com/docs/2.0/building-docker-images/#accessing-services)。\n+\n+今回のケースでは、プライベートレジストリを利用する都合とネットワーク的な制約を抱えています。バックエンドのコンテナ群を動かして E2E テストで利用するために、E2E テストも Remote Docker Environment のコンテナで実行する必要がありました。\n+\n+制約といえば、primary container のファイルシステムを Remote Docker Environment のコンテナからマウントする事もできません。primary container のキャッシュは便利ですが、そのキャッシュを Remote Docker Environment でも無条件に利用する事はできません。直接マウントはできないので、[`docker cp` でコンテナにコピーする方法が提案されています](https://circleci.com/docs/2.0/building-docker-images/#mounting-folders)。","path":"source/posts/2017-05-08-run-e2e-test-on-circleci-2_0.html.md","position":null,"original_position":130,"commit_id":"2dd5e633bc84f02d9023dc1583de4992916494d3","original_commit_id":"67a73be298d04724eab9fbc404df0b78dca92ab7","user":{"login":"koshigoe","id":18269,"avatar_url":"https://avatars2.githubusercontent.com/u/18269?v=3","gravatar_id":"","url":"https://api.github.com/users/koshigoe","html_url":"https://github.com/koshigoe","followers_url":"https://api.github.com/users/koshigoe/followers","following_url":"https://api.github.com/users/koshigoe/following{/other_user}","gists_url":"https://api.github.com/users/koshigoe/gists{/gist_id}","starred_url":"https://api.github.com/users/koshigoe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/koshigoe/subscriptions","organizations_url":"https://api.github.com/users/koshigoe/orgs","repos_url":"https://api.github.com/users/koshigoe/repos","events_url":"https://api.github.com/users/koshigoe/events{/privacy}","received_events_url":"https://api.github.com/users/koshigoe/received_events","type":"User","site_admin":false},"body":"37c69e6 でバッククォートを使うのやめました。","created_at":"2017-05-01T04:30:15Z","updated_at":"2017-05-01T04:30:15Z","html_url":"https://github.com/feedforce/tech.feedforce.jp/pull/243#discussion_r114097643","pull_request_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/243","_links":{"self":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/comments/114097643"},"html":{"href":"https://github.com/feedforce/tech.feedforce.jp/pull/243#discussion_r114097643"},"pull_request":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/243"}}},"pull_request":{"url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/243","id":118276642,"html_url":"https://github.com/feedforce/tech.feedforce.jp/pull/243","diff_url":"https://github.com/feedforce/tech.feedforce.jp/pull/243.diff","patch_url":"https://github.com/feedforce/tech.feedforce.jp/pull/243.patch","issue_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues/243","number":243,"state":"open","locked":false,"title":"[公開するならGWあけ5/8かな] Add article \"E2E テストを CircleCI 2.0 (Beta) で完結させてみた話\"","user":{"login":"koshigoe","id":18269,"avatar_url":"https://avatars2.githubusercontent.com/u/18269?v=3","gravatar_id":"","url":"https://api.github.com/users/koshigoe","html_url":"https://github.com/koshigoe","followers_url":"https://api.github.com/users/koshigoe/followers","following_url":"https://api.github.com/users/koshigoe/following{/other_user}","gists_url":"https://api.github.com/users/koshigoe/gists{/gist_id}","starred_url":"https://api.github.com/users/koshigoe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/koshigoe/subscriptions","organizations_url":"https://api.github.com/users/koshigoe/orgs","repos_url":"https://api.github.com/users/koshigoe/repos","events_url":"https://api.github.com/users/koshigoe/events{/privacy}","received_events_url":"https://api.github.com/users/koshigoe/received_events","type":"User","site_admin":false},"body":"### TODO\r\n\r\n* [ ] `date` とファイル名を公開日に合わせる\r\n\r\n### 概要\r\n\r\n* dfplus.io で実験的に取り組んでいる E2E テストのコンテナを使った改善について書きました\r\n\r\n### 合わせてやったこと\r\n\r\n* 最近自分のアイコンを変えたので、合わせてこれも変えました\r\n\r\n### 特に確認してほしいこと\r\n\r\n* まだ運用始めてない話を書いてしまっているけど…\r\n* 文章構成など考えず勢いで書き切ったので、読んでも全く伝わらないという事が心配です\r\n* 対象読者など考えず勢いで書き切ったので、読んでも全く伝わらないという事が心配です\r\n* 勢いで書き切ったので、構成・内容・分量に自信がありません\r\n* 日本語に自信がありません\r\n","created_at":"2017-04-29T14:23:52Z","updated_at":"2017-05-01T04:30:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6b262a12820ea0ca76a2b5e51cd4d304d84ee4da","assignee":{"login":"koshigoe","id":18269,"avatar_url":"https://avatars2.githubusercontent.com/u/18269?v=3","gravatar_id":"","url":"https://api.github.com/users/koshigoe","html_url":"https://github.com/koshigoe","followers_url":"https://api.github.com/users/koshigoe/followers","following_url":"https://api.github.com/users/koshigoe/following{/other_user}","gists_url":"https://api.github.com/users/koshigoe/gists{/gist_id}","starred_url":"https://api.github.com/users/koshigoe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/koshigoe/subscriptions","organizations_url":"https://api.github.com/users/koshigoe/orgs","repos_url":"https://api.github.com/users/koshigoe/repos","events_url":"https://api.github.com/users/koshigoe/events{/privacy}","received_events_url":"https://api.github.com/users/koshigoe/received_events","type":"User","site_admin":false},"assignees":[{"login":"koshigoe","id":18269,"avatar_url":"https://avatars2.githubusercontent.com/u/18269?v=3","gravatar_id":"","url":"https://api.github.com/users/koshigoe","html_url":"https://github.com/koshigoe","followers_url":"https://api.github.com/users/koshigoe/followers","following_url":"https://api.github.com/users/koshigoe/following{/other_user}","gists_url":"https://api.github.com/users/koshigoe/gists{/gist_id}","starred_url":"https://api.github.com/users/koshigoe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/koshigoe/subscriptions","organizations_url":"https://api.github.com/users/koshigoe/orgs","repos_url":"https://api.github.com/users/koshigoe/repos","events_url":"https://api.github.com/users/koshigoe/events{/privacy}","received_events_url":"https://api.github.com/users/koshigoe/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/243/commits","review_comments_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/243/comments","review_comment_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/comments{/number}","comments_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues/243/comments","statuses_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/statuses/2dd5e633bc84f02d9023dc1583de4992916494d3","head":{"label":"feedforce:article/run-e2e-test-on-circleci","ref":"article/run-e2e-test-on-circleci","sha":"2dd5e633bc84f02d9023dc1583de4992916494d3","user":{"login":"feedforce","id":4169389,"avatar_url":"https://avatars0.githubusercontent.com/u/4169389?v=3","gravatar_id":"","url":"https://api.github.com/users/feedforce","html_url":"https://github.com/feedforce","followers_url":"https://api.github.com/users/feedforce/followers","following_url":"https://api.github.com/users/feedforce/following{/other_user}","gists_url":"https://api.github.com/users/feedforce/gists{/gist_id}","starred_url":"https://api.github.com/users/feedforce/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/feedforce/subscriptions","organizations_url":"https://api.github.com/users/feedforce/orgs","repos_url":"https://api.github.com/users/feedforce/repos","events_url":"https://api.github.com/users/feedforce/events{/privacy}","received_events_url":"https://api.github.com/users/feedforce/received_events","type":"Organization","site_admin":false},"repo":{"id":27247535,"name":"tech.feedforce.jp","full_name":"feedforce/tech.feedforce.jp","owner":{"login":"feedforce","id":4169389,"avatar_url":"https://avatars0.githubusercontent.com/u/4169389?v=3","gravatar_id":"","url":"https://api.github.com/users/feedforce","html_url":"https://github.com/feedforce","followers_url":"https://api.github.com/users/feedforce/followers","following_url":"https://api.github.com/users/feedforce/following{/other_user}","gists_url":"https://api.github.com/users/feedforce/gists{/gist_id}","starred_url":"https://api.github.com/users/feedforce/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/feedforce/subscriptions","organizations_url":"https://api.github.com/users/feedforce/orgs","repos_url":"https://api.github.com/users/feedforce/repos","events_url":"https://api.github.com/users/feedforce/events{/privacy}","received_events_url":"https://api.github.com/users/feedforce/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/feedforce/tech.feedforce.jp","description":"feedforce Engineers' blog","fork":false,"url":"https://api.github.com/repos/feedforce/tech.feedforce.jp","forks_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/forks","keys_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/teams","hooks_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/hooks","issue_events_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues/events{/number}","events_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/events","assignees_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/assignees{/user}","branches_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/branches{/branch}","tags_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/tags","blobs_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/refs{/sha}","trees_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/statuses/{sha}","languages_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/languages","stargazers_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/stargazers","contributors_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/contributors","subscribers_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/subscribers","subscription_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/subscription","commits_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/commits{/sha}","git_commits_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/commits{/sha}","comments_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/comments{/number}","issue_comment_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues/comments{/number}","contents_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/contents/{+path}","compare_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/merges","archive_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/downloads","issues_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues{/number}","pulls_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls{/number}","milestones_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/milestones{/number}","notifications_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/labels{/name}","releases_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/releases{/id}","deployments_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/deployments","created_at":"2014-11-28T01:42:34Z","updated_at":"2016-10-26T01:22:02Z","pushed_at":"2017-05-01T04:29:59Z","git_url":"git://github.com/feedforce/tech.feedforce.jp.git","ssh_url":"git@github.com:feedforce/tech.feedforce.jp.git","clone_url":"https://github.com/feedforce/tech.feedforce.jp.git","svn_url":"https://github.com/feedforce/tech.feedforce.jp","homepage":"http://tech.feedforce.jp/","size":56817,"stargazers_count":7,"watchers_count":7,"language":"CSS","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":4,"mirror_url":null,"open_issues_count":4,"forks":4,"open_issues":4,"watchers":7,"default_branch":"master"}},"base":{"label":"feedforce:master","ref":"master","sha":"5fd4b7d35aa40dfa78053f69a4ed49e2ad1558e1","user":{"login":"feedforce","id":4169389,"avatar_url":"https://avatars0.githubusercontent.com/u/4169389?v=3","gravatar_id":"","url":"https://api.github.com/users/feedforce","html_url":"https://github.com/feedforce","followers_url":"https://api.github.com/users/feedforce/followers","following_url":"https://api.github.com/users/feedforce/following{/other_user}","gists_url":"https://api.github.com/users/feedforce/gists{/gist_id}","starred_url":"https://api.github.com/users/feedforce/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/feedforce/subscriptions","organizations_url":"https://api.github.com/users/feedforce/orgs","repos_url":"https://api.github.com/users/feedforce/repos","events_url":"https://api.github.com/users/feedforce/events{/privacy}","received_events_url":"https://api.github.com/users/feedforce/received_events","type":"Organization","site_admin":false},"repo":{"id":27247535,"name":"tech.feedforce.jp","full_name":"feedforce/tech.feedforce.jp","owner":{"login":"feedforce","id":4169389,"avatar_url":"https://avatars0.githubusercontent.com/u/4169389?v=3","gravatar_id":"","url":"https://api.github.com/users/feedforce","html_url":"https://github.com/feedforce","followers_url":"https://api.github.com/users/feedforce/followers","following_url":"https://api.github.com/users/feedforce/following{/other_user}","gists_url":"https://api.github.com/users/feedforce/gists{/gist_id}","starred_url":"https://api.github.com/users/feedforce/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/feedforce/subscriptions","organizations_url":"https://api.github.com/users/feedforce/orgs","repos_url":"https://api.github.com/users/feedforce/repos","events_url":"https://api.github.com/users/feedforce/events{/privacy}","received_events_url":"https://api.github.com/users/feedforce/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/feedforce/tech.feedforce.jp","description":"feedforce Engineers' blog","fork":false,"url":"https://api.github.com/repos/feedforce/tech.feedforce.jp","forks_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/forks","keys_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/teams","hooks_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/hooks","issue_events_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues/events{/number}","events_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/events","assignees_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/assignees{/user}","branches_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/branches{/branch}","tags_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/tags","blobs_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/refs{/sha}","trees_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/statuses/{sha}","languages_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/languages","stargazers_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/stargazers","contributors_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/contributors","subscribers_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/subscribers","subscription_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/subscription","commits_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/commits{/sha}","git_commits_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/git/commits{/sha}","comments_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/comments{/number}","issue_comment_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues/comments{/number}","contents_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/contents/{+path}","compare_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/merges","archive_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/downloads","issues_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues{/number}","pulls_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls{/number}","milestones_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/milestones{/number}","notifications_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/labels{/name}","releases_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/releases{/id}","deployments_url":"https://api.github.com/repos/feedforce/tech.feedforce.jp/deployments","created_at":"2014-11-28T01:42:34Z","updated_at":"2016-10-26T01:22:02Z","pushed_at":"2017-05-01T04:29:59Z","git_url":"git://github.com/feedforce/tech.feedforce.jp.git","ssh_url":"git@github.com:feedforce/tech.feedforce.jp.git","clone_url":"https://github.com/feedforce/tech.feedforce.jp.git","svn_url":"https://github.com/feedforce/tech.feedforce.jp","homepage":"http://tech.feedforce.jp/","size":56817,"stargazers_count":7,"watchers_count":7,"language":"CSS","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":4,"mirror_url":null,"open_issues_count":4,"forks":4,"open_issues":4,"watchers":7,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/243"},"html":{"href":"https://github.com/feedforce/tech.feedforce.jp/pull/243"},"issue":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues/243"},"comments":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/issues/243/comments"},"review_comments":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/243/comments"},"review_comment":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/pulls/243/commits"},"statuses":{"href":"https://api.github.com/repos/feedforce/tech.feedforce.jp/statuses/2dd5e633bc84f02d9023dc1583de4992916494d3"}}}}
{"actor":{"display_login":"koshigoe"}}