{"action":"created","comment":{"url":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/comments/185386254","pull_request_review_id":116762619,"id":185386254,"diff_hunk":"@@ -17,10 +18,11 @@ import (\n \tma \"github.com/multiformats/go-multiaddr\"\n )\n \n-// Common errors\n-var (\n-\tErrBootstrap = errors.New(\"bootstrap unsuccessful\")\n-)\n+// ReadyTimeout specifies the  before giving up","path":"cluster.go","position":22,"original_position":22,"commit_id":"28add34d7d966eee1b973f249186fa887dc3295d","original_commit_id":"28add34d7d966eee1b973f249186fa887dc3295d","user":{"login":"ZenGround0","id":5515260,"avatar_url":"https://avatars2.githubusercontent.com/u/5515260?v=4","gravatar_id":"","url":"https://api.github.com/users/ZenGround0","html_url":"https://github.com/ZenGround0","followers_url":"https://api.github.com/users/ZenGround0/followers","following_url":"https://api.github.com/users/ZenGround0/following{/other_user}","gists_url":"https://api.github.com/users/ZenGround0/gists{/gist_id}","starred_url":"https://api.github.com/users/ZenGround0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ZenGround0/subscriptions","organizations_url":"https://api.github.com/users/ZenGround0/orgs","repos_url":"https://api.github.com/users/ZenGround0/repos","events_url":"https://api.github.com/users/ZenGround0/events{/privacy}","received_events_url":"https://api.github.com/users/ZenGround0/received_events","type":"User","site_admin":false},"body":"\"specifies the  before\" -> \"specifies the time before\"","created_at":"2018-05-02T03:30:55Z","updated_at":"2018-05-02T03:42:25Z","html_url":"https://github.com/ipfs/ipfs-cluster/pull/398#discussion_r185386254","pull_request_url":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/398","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/comments/185386254"},"html":{"href":"https://github.com/ipfs/ipfs-cluster/pull/398#discussion_r185386254"},"pull_request":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/398"}}},"pull_request":{"url":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/398","id":184824864,"html_url":"https://github.com/ipfs/ipfs-cluster/pull/398","diff_url":"https://github.com/ipfs/ipfs-cluster/pull/398.diff","patch_url":"https://github.com/ipfs/ipfs-cluster/pull/398.patch","issue_url":"https://api.github.com/repos/ipfs/ipfs-cluster/issues/398","number":398,"state":"open","locked":false,"title":"Emancipate the consensus component","user":{"login":"hsanjuan","id":1027022,"avatar_url":"https://avatars3.githubusercontent.com/u/1027022?v=4","gravatar_id":"","url":"https://api.github.com/users/hsanjuan","html_url":"https://github.com/hsanjuan","followers_url":"https://api.github.com/users/hsanjuan/followers","following_url":"https://api.github.com/users/hsanjuan/following{/other_user}","gists_url":"https://api.github.com/users/hsanjuan/gists{/gist_id}","starred_url":"https://api.github.com/users/hsanjuan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hsanjuan/subscriptions","organizations_url":"https://api.github.com/users/hsanjuan/orgs","repos_url":"https://api.github.com/users/hsanjuan/repos","events_url":"https://api.github.com/users/hsanjuan/events{/privacy}","received_events_url":"https://api.github.com/users/hsanjuan/received_events","type":"User","site_admin":false},"body":"This commit promotes the Consensus component (and Raft) to become a fully\r\nindependent thing like other components, passed to NewCluster during\r\ninitialization. Cluster (main component) no longer creates the consensus\r\nlayer internally. This has triggered a number of breaking changes\r\nthat I will explain below.\r\n\r\nMotivation: Future work will require the possibility of running Cluster\r\nwith a consensus layer that is not Raft. The \"consensus\" layer is in charge\r\nof maintaining two things:\r\n  * The current cluster peerset, as required by the implementation\r\n  * The current cluster pinset (shared state)\r\n\r\nWhile the pinset maintenance has always been in the consensus layer, the\r\npeerset maintenance was handled by the main component (starting by the \"peers\"\r\nkey in the configuration) AND the Raft component (internally)\r\nand this generated lots of confusion: if the user edited the peers in the\r\nconfiguration they would be greeted with an error.\r\n\r\nThe bootstrap process (adding a peer to an existing cluster) and configuration\r\nkey also complicated many things, since the main component did it, but only\r\nwhen the consensus was initialized and in single peer mode.\r\n\r\nIn all this we also mixed the peerstore (list of peer addresses in the libp2p\r\nhost) with the peerset, when they need not to be linked.\r\n\r\nBy initializing the consensus layer before calling NewCluster, all the\r\ndifficulties in maintaining the current implementation in the same way\r\nhave come to light. Thus, the following changes have been introduced:\r\n\r\n* Remove \"peers\" and \"bootstrap\" keys from the configuration: we no longer\r\nedit or save the configuration files. This was a very bad practice, requiring\r\nwrite permissions by the process to the file containing the private key and\r\nadditionally made things like Puppet deployments of cluster difficult as\r\nconfiguration would mutate from its initial version. Needless to say all the\r\nmaintenance associated to making sure peers and bootstrap had correct values\r\nwhen peers are bootstrapped or removed. A loud and detailed error message has\r\nbeen added when staring cluster with an old config, along with instructions on\r\nhow to move forward.\r\n\r\n* Introduce a PeerstoreFile (\"peerstore\") which stores peer addresses: in\r\nipfs, the peerstore is not persisted because it can be re-built from the\r\nnetwork bootstrappers and the DHT. Cluster should probably also allow\r\ndiscoverability of peers addresses (when not bootstrapping, as in that case\r\nwe have it), but in the meantime, we will read and persist the peerstore\r\naddresses for cluster peers in this file, different from the configuration.\r\nNote that dns multiaddresses are now fully supported and no IPs are saved\r\nwhen we have DNS multiaddresses for a peer.\r\n\r\n* The former \"peer_manager\" code is now a pstoremgr module, providing utilities\r\nto parse, add, list and generally maintain the libp2p host peerstore, including\r\noperations on the PeerstoreFile. This \"pstoremgr\" can now also be extended to\r\nperform address autodiscovery and other things indepedently from Cluster.\r\n\r\n* Create and initialize Raft outside of the main Cluster component: since we\r\ncan now launch Raft independently from Cluster, we have more degrees of\r\nfreedom. A new \"staging\" option when creating the object allows a raft peer to\r\nbe launched in Staging mode, waiting to be added to a running consensus, and\r\nthus, not electing itself as leader or doing anything like we were doing\r\nbefore. This additionally allows us to track when the peer has become a\r\nVoter, which only happens when it's caught up with the state, something that\r\nwas wonky previously.\r\n\r\n* The raft configuration now includes an InitPeerset key, which allows to\r\nprovide a peerset for new peers and which is ignored when staging==true. The\r\nwhole Raft initialization code is way cleaner and stronger now.\r\n\r\n* Cluster peer bootsrapping is now an ipfs-cluster-service feature. The\r\n--bootstrap flag works as before (additionally allowing comma-separated-list\r\nof entries). What bootstrap does, is to initialize Raft with staging == true,\r\nand then call Join in the main cluster component. Only when the Raft peer\r\ntransitions to Voter, consensus becomes ready, and cluster becomes Ready.\r\nThis is cleaner, works better and is less complex than before (supporting\r\nboth flags and config values). We also backup and clean the state whenever\r\nwe are boostrapping, automatically\r\n\r\n* ipfs-cluster-service no longer runs the daemon. Starting cluster needs\r\nnow \"ipfs-cluster-service daemon\". The daemon specific flags (bootstrap,\r\nalloc) are now flags for the daemon subcommand. Here we mimic ipfs (\"ipfs\"\r\ndoes not start the daemon but print help) and pave the path for merging both\r\nservice and ctl in the future.\r\n\r\nWhile this brings some breaking changes, it significantly reduces the\r\ncomplexity of the configuration, the code and most importantly, the\r\ndocumentation. It should be easier now to explain the user what is the\r\nright way to launch a cluster peer, and more difficult to make mistakes.\r\n\r\nAs a side effect, the PR also:\r\n\r\n* Fixes #381 - peers with dynamic addresses\r\n* Fixes #371 - peers should be Raft configuration option\r\n* Fixes #378 - waitForUpdates may return before state fully synced\r\n* Fixes #235 - config option shadowing (no cfg saves, no need to shadow)","created_at":"2018-04-29T08:55:48Z","updated_at":"2018-05-02T03:42:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e8e84d2dfb0d4ecf3a8aeb17dd068abeb953f1d9","assignee":{"login":"hsanjuan","id":1027022,"avatar_url":"https://avatars3.githubusercontent.com/u/1027022?v=4","gravatar_id":"","url":"https://api.github.com/users/hsanjuan","html_url":"https://github.com/hsanjuan","followers_url":"https://api.github.com/users/hsanjuan/followers","following_url":"https://api.github.com/users/hsanjuan/following{/other_user}","gists_url":"https://api.github.com/users/hsanjuan/gists{/gist_id}","starred_url":"https://api.github.com/users/hsanjuan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hsanjuan/subscriptions","organizations_url":"https://api.github.com/users/hsanjuan/orgs","repos_url":"https://api.github.com/users/hsanjuan/repos","events_url":"https://api.github.com/users/hsanjuan/events{/privacy}","received_events_url":"https://api.github.com/users/hsanjuan/received_events","type":"User","site_admin":false},"assignees":[{"login":"hsanjuan","id":1027022,"avatar_url":"https://avatars3.githubusercontent.com/u/1027022?v=4","gravatar_id":"","url":"https://api.github.com/users/hsanjuan","html_url":"https://github.com/hsanjuan","followers_url":"https://api.github.com/users/hsanjuan/followers","following_url":"https://api.github.com/users/hsanjuan/following{/other_user}","gists_url":"https://api.github.com/users/hsanjuan/gists{/gist_id}","starred_url":"https://api.github.com/users/hsanjuan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hsanjuan/subscriptions","organizations_url":"https://api.github.com/users/hsanjuan/orgs","repos_url":"https://api.github.com/users/hsanjuan/repos","events_url":"https://api.github.com/users/hsanjuan/events{/privacy}","received_events_url":"https://api.github.com/users/hsanjuan/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"lanzafame","id":5924712,"avatar_url":"https://avatars0.githubusercontent.com/u/5924712?v=4","gravatar_id":"","url":"https://api.github.com/users/lanzafame","html_url":"https://github.com/lanzafame","followers_url":"https://api.github.com/users/lanzafame/followers","following_url":"https://api.github.com/users/lanzafame/following{/other_user}","gists_url":"https://api.github.com/users/lanzafame/gists{/gist_id}","starred_url":"https://api.github.com/users/lanzafame/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lanzafame/subscriptions","organizations_url":"https://api.github.com/users/lanzafame/orgs","repos_url":"https://api.github.com/users/lanzafame/repos","events_url":"https://api.github.com/users/lanzafame/events{/privacy}","received_events_url":"https://api.github.com/users/lanzafame/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":510842526,"url":"https://api.github.com/repos/ipfs/ipfs-cluster/labels/in%20progress","name":"in progress","color":"fbca04","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/398/commits","review_comments_url":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/398/comments","review_comment_url":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ipfs/ipfs-cluster/issues/398/comments","statuses_url":"https://api.github.com/repos/ipfs/ipfs-cluster/statuses/28add34d7d966eee1b973f249186fa887dc3295d","head":{"label":"ipfs:feat/promote-consensus","ref":"feat/promote-consensus","sha":"28add34d7d966eee1b973f249186fa887dc3295d","user":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars0.githubusercontent.com/u/10536621?v=4","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"repo":{"id":62413100,"name":"ipfs-cluster","full_name":"ipfs/ipfs-cluster","owner":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars0.githubusercontent.com/u/10536621?v=4","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ipfs/ipfs-cluster","description":"Pinset orchestration for IPFS","fork":false,"url":"https://api.github.com/repos/ipfs/ipfs-cluster","forks_url":"https://api.github.com/repos/ipfs/ipfs-cluster/forks","keys_url":"https://api.github.com/repos/ipfs/ipfs-cluster/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ipfs/ipfs-cluster/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ipfs/ipfs-cluster/teams","hooks_url":"https://api.github.com/repos/ipfs/ipfs-cluster/hooks","issue_events_url":"https://api.github.com/repos/ipfs/ipfs-cluster/issues/events{/number}","events_url":"https://api.github.com/repos/ipfs/ipfs-cluster/events","assignees_url":"https://api.github.com/repos/ipfs/ipfs-cluster/assignees{/user}","branches_url":"https://api.github.com/repos/ipfs/ipfs-cluster/branches{/branch}","tags_url":"https://api.github.com/repos/ipfs/ipfs-cluster/tags","blobs_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/refs{/sha}","trees_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ipfs/ipfs-cluster/statuses/{sha}","languages_url":"https://api.github.com/repos/ipfs/ipfs-cluster/languages","stargazers_url":"https://api.github.com/repos/ipfs/ipfs-cluster/stargazers","contributors_url":"https://api.github.com/repos/ipfs/ipfs-cluster/contributors","subscribers_url":"https://api.github.com/repos/ipfs/ipfs-cluster/subscribers","subscription_url":"https://api.github.com/repos/ipfs/ipfs-cluster/subscription","commits_url":"https://api.github.com/repos/ipfs/ipfs-cluster/commits{/sha}","git_commits_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/commits{/sha}","comments_url":"https://api.github.com/repos/ipfs/ipfs-cluster/comments{/number}","issue_comment_url":"https://api.github.com/repos/ipfs/ipfs-cluster/issues/comments{/number}","contents_url":"https://api.github.com/repos/ipfs/ipfs-cluster/contents/{+path}","compare_url":"https://api.github.com/repos/ipfs/ipfs-cluster/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ipfs/ipfs-cluster/merges","archive_url":"https://api.github.com/repos/ipfs/ipfs-cluster/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ipfs/ipfs-cluster/downloads","issues_url":"https://api.github.com/repos/ipfs/ipfs-cluster/issues{/number}","pulls_url":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls{/number}","milestones_url":"https://api.github.com/repos/ipfs/ipfs-cluster/milestones{/number}","notifications_url":"https://api.github.com/repos/ipfs/ipfs-cluster/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ipfs/ipfs-cluster/labels{/name}","releases_url":"https://api.github.com/repos/ipfs/ipfs-cluster/releases{/id}","deployments_url":"https://api.github.com/repos/ipfs/ipfs-cluster/deployments","created_at":"2016-07-01T18:41:15Z","updated_at":"2018-05-01T09:14:20Z","pushed_at":"2018-05-02T03:08:30Z","git_url":"git://github.com/ipfs/ipfs-cluster.git","ssh_url":"git@github.com:ipfs/ipfs-cluster.git","clone_url":"https://github.com/ipfs/ipfs-cluster.git","svn_url":"https://github.com/ipfs/ipfs-cluster","homepage":"https://cluster.ipfs.io","size":2230,"stargazers_count":249,"watchers_count":249,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":38,"mirror_url":null,"archived":false,"open_issues_count":72,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":38,"open_issues":72,"watchers":249,"default_branch":"master"}},"base":{"label":"ipfs:master","ref":"master","sha":"dbcc5c2fde0dc6f563d30d4068112fc3ff60317b","user":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars0.githubusercontent.com/u/10536621?v=4","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"repo":{"id":62413100,"name":"ipfs-cluster","full_name":"ipfs/ipfs-cluster","owner":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars0.githubusercontent.com/u/10536621?v=4","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ipfs/ipfs-cluster","description":"Pinset orchestration for IPFS","fork":false,"url":"https://api.github.com/repos/ipfs/ipfs-cluster","forks_url":"https://api.github.com/repos/ipfs/ipfs-cluster/forks","keys_url":"https://api.github.com/repos/ipfs/ipfs-cluster/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ipfs/ipfs-cluster/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ipfs/ipfs-cluster/teams","hooks_url":"https://api.github.com/repos/ipfs/ipfs-cluster/hooks","issue_events_url":"https://api.github.com/repos/ipfs/ipfs-cluster/issues/events{/number}","events_url":"https://api.github.com/repos/ipfs/ipfs-cluster/events","assignees_url":"https://api.github.com/repos/ipfs/ipfs-cluster/assignees{/user}","branches_url":"https://api.github.com/repos/ipfs/ipfs-cluster/branches{/branch}","tags_url":"https://api.github.com/repos/ipfs/ipfs-cluster/tags","blobs_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/refs{/sha}","trees_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ipfs/ipfs-cluster/statuses/{sha}","languages_url":"https://api.github.com/repos/ipfs/ipfs-cluster/languages","stargazers_url":"https://api.github.com/repos/ipfs/ipfs-cluster/stargazers","contributors_url":"https://api.github.com/repos/ipfs/ipfs-cluster/contributors","subscribers_url":"https://api.github.com/repos/ipfs/ipfs-cluster/subscribers","subscription_url":"https://api.github.com/repos/ipfs/ipfs-cluster/subscription","commits_url":"https://api.github.com/repos/ipfs/ipfs-cluster/commits{/sha}","git_commits_url":"https://api.github.com/repos/ipfs/ipfs-cluster/git/commits{/sha}","comments_url":"https://api.github.com/repos/ipfs/ipfs-cluster/comments{/number}","issue_comment_url":"https://api.github.com/repos/ipfs/ipfs-cluster/issues/comments{/number}","contents_url":"https://api.github.com/repos/ipfs/ipfs-cluster/contents/{+path}","compare_url":"https://api.github.com/repos/ipfs/ipfs-cluster/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ipfs/ipfs-cluster/merges","archive_url":"https://api.github.com/repos/ipfs/ipfs-cluster/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ipfs/ipfs-cluster/downloads","issues_url":"https://api.github.com/repos/ipfs/ipfs-cluster/issues{/number}","pulls_url":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls{/number}","milestones_url":"https://api.github.com/repos/ipfs/ipfs-cluster/milestones{/number}","notifications_url":"https://api.github.com/repos/ipfs/ipfs-cluster/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ipfs/ipfs-cluster/labels{/name}","releases_url":"https://api.github.com/repos/ipfs/ipfs-cluster/releases{/id}","deployments_url":"https://api.github.com/repos/ipfs/ipfs-cluster/deployments","created_at":"2016-07-01T18:41:15Z","updated_at":"2018-05-01T09:14:20Z","pushed_at":"2018-05-02T03:08:30Z","git_url":"git://github.com/ipfs/ipfs-cluster.git","ssh_url":"git@github.com:ipfs/ipfs-cluster.git","clone_url":"https://github.com/ipfs/ipfs-cluster.git","svn_url":"https://github.com/ipfs/ipfs-cluster","homepage":"https://cluster.ipfs.io","size":2230,"stargazers_count":249,"watchers_count":249,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":38,"mirror_url":null,"archived":false,"open_issues_count":72,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":38,"open_issues":72,"watchers":249,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/398"},"html":{"href":"https://github.com/ipfs/ipfs-cluster/pull/398"},"issue":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/issues/398"},"comments":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/issues/398/comments"},"review_comments":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/398/comments"},"review_comment":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/pulls/398/commits"},"statuses":{"href":"https://api.github.com/repos/ipfs/ipfs-cluster/statuses/28add34d7d966eee1b973f249186fa887dc3295d"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"ZenGround0"}}