{"action":"created","comment":{"url":"https://api.github.com/repos/Originate/git-town/pulls/comments/28121730","id":28121730,"diff_hunk":"@@ -104,6 +104,27 @@ For discussion around this architecture see\n where it was proposed.\n \n \n+### Drivers\n+\n+_Drivers_ implement third-party specific functionality in a standardized way.\n+For example, the [GitHub driver](./src/drivers/code_hosting/github.sh)\n+implements GitHub-related operations like creating a pull request there.\n+\n+There is also a similar\n+[Bitbucket driver](./src/drivers/code_hosting/bitbucket.sh)\n+that does the same things on Bitbucket.\n+Both drivers are part of the _driver family_ for","path":"CONTRIBUTING.md","position":22,"original_position":22,"commit_id":"6f5e354585e5beed842b6f95c48c7341c74fc50b","original_commit_id":"4c33f116c87fa4c63fe134fd472d2f377c465a4d","user":{"login":"kevgo","id":268934,"avatar_url":"https://avatars.githubusercontent.com/u/268934?v=3","gravatar_id":"","url":"https://api.github.com/users/kevgo","html_url":"https://github.com/kevgo","followers_url":"https://api.github.com/users/kevgo/followers","following_url":"https://api.github.com/users/kevgo/following{/other_user}","gists_url":"https://api.github.com/users/kevgo/gists{/gist_id}","starred_url":"https://api.github.com/users/kevgo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kevgo/subscriptions","organizations_url":"https://api.github.com/users/kevgo/orgs","repos_url":"https://api.github.com/users/kevgo/repos","events_url":"https://api.github.com/users/kevgo/events{/privacy}","received_events_url":"https://api.github.com/users/kevgo/received_events","type":"User","site_admin":false},"body":"done","created_at":"2015-04-10T04:16:24Z","updated_at":"2015-04-10T04:16:24Z","html_url":"https://github.com/Originate/git-town/pull/483#discussion_r28121730","pull_request_url":"https://api.github.com/repos/Originate/git-town/pulls/483","_links":{"self":{"href":"https://api.github.com/repos/Originate/git-town/pulls/comments/28121730"},"html":{"href":"https://github.com/Originate/git-town/pull/483#discussion_r28121730"},"pull_request":{"href":"https://api.github.com/repos/Originate/git-town/pulls/483"}}},"pull_request":{"url":"https://api.github.com/repos/Originate/git-town/pulls/483","id":32657832,"html_url":"https://github.com/Originate/git-town/pull/483","diff_url":"https://github.com/Originate/git-town/pull/483.diff","patch_url":"https://github.com/Originate/git-town/pull/483.patch","issue_url":"https://api.github.com/repos/Originate/git-town/issues/483","number":483,"state":"open","locked":false,"title":"Initial driver architecture","user":{"login":"kevgo","id":268934,"avatar_url":"https://avatars.githubusercontent.com/u/268934?v=3","gravatar_id":"","url":"https://api.github.com/users/kevgo","html_url":"https://github.com/kevgo","followers_url":"https://api.github.com/users/kevgo/followers","following_url":"https://api.github.com/users/kevgo/following{/other_user}","gists_url":"https://api.github.com/users/kevgo/gists{/gist_id}","starred_url":"https://api.github.com/users/kevgo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kevgo/subscriptions","organizations_url":"https://api.github.com/users/kevgo/orgs","repos_url":"https://api.github.com/users/kevgo/repos","events_url":"https://api.github.com/users/kevgo/events{/privacy}","received_events_url":"https://api.github.com/users/kevgo/received_events","type":"User","site_admin":false},"body":"@charlierudolph @allewun @ricmatsui \r\n\r\nThis is a first attempt at separating third-party specific functionality into \"drivers\" for those third-party APIs, as a parts of #477. The first driver family created here is around code hosting (GitHub, Bitbucket), with another driver family around CI coming soon (CircleCI, Travis, etc).\r\n\r\nThe motivation for this change is that this makes it much easier to add support for additional third-party systems.\r\n\r\nThe right patterns to use here is certainly a topic for great debates, and I have gone back and forth (in my head) on the various solutions. On the simple side we have a simple driver infrastructure like in this PR. On the complex side is a full extension system that can define its own Git commands, integration tests, and helpers, which can depend on each other, and be loaded through our own package manager. Following KISS and YAGNI as principles that have always served me very well, this PR contains the simplest possible approach, as a start. I'm happy to add more complexity when it is really needed and makes things simpler. In Bash one doesn't want to over-engineer things!\r\n\r\nI don't want to explain the changes too much myself here. The architecture should be documented sufficiently in the developer documentation changes in this PR. If it leaves anything unclear, please let me know, and I'll add more details there, so that they are around for everybody to understand.\r\n\r\nWhat do you think?","created_at":"2015-04-06T01:26:06Z","updated_at":"2015-04-10T04:16:24Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9309ced76d8826b8c8b44e2b04b2e05fb265a857","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Originate/git-town/pulls/483/commits","review_comments_url":"https://api.github.com/repos/Originate/git-town/pulls/483/comments","review_comment_url":"https://api.github.com/repos/Originate/git-town/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Originate/git-town/issues/483/comments","statuses_url":"https://api.github.com/repos/Originate/git-town/statuses/6f5e354585e5beed842b6f95c48c7341c74fc50b","head":{"label":"Originate:kg-extensions-1","ref":"kg-extensions-1","sha":"6f5e354585e5beed842b6f95c48c7341c74fc50b","user":{"login":"Originate","id":1627168,"avatar_url":"https://avatars.githubusercontent.com/u/1627168?v=3","gravatar_id":"","url":"https://api.github.com/users/Originate","html_url":"https://github.com/Originate","followers_url":"https://api.github.com/users/Originate/followers","following_url":"https://api.github.com/users/Originate/following{/other_user}","gists_url":"https://api.github.com/users/Originate/gists{/gist_id}","starred_url":"https://api.github.com/users/Originate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Originate/subscriptions","organizations_url":"https://api.github.com/users/Originate/orgs","repos_url":"https://api.github.com/users/Originate/repos","events_url":"https://api.github.com/users/Originate/events{/privacy}","received_events_url":"https://api.github.com/users/Originate/received_events","type":"Organization","site_admin":false},"repo":{"id":19825320,"name":"git-town","full_name":"Originate/git-town","owner":{"login":"Originate","id":1627168,"avatar_url":"https://avatars.githubusercontent.com/u/1627168?v=3","gravatar_id":"","url":"https://api.github.com/users/Originate","html_url":"https://github.com/Originate","followers_url":"https://api.github.com/users/Originate/followers","following_url":"https://api.github.com/users/Originate/following{/other_user}","gists_url":"https://api.github.com/users/Originate/gists{/gist_id}","starred_url":"https://api.github.com/users/Originate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Originate/subscriptions","organizations_url":"https://api.github.com/users/Originate/orgs","repos_url":"https://api.github.com/users/Originate/repos","events_url":"https://api.github.com/users/Originate/events{/privacy}","received_events_url":"https://api.github.com/users/Originate/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Originate/git-town","description":"Git extensions for robust, high-level development workflows","fork":false,"url":"https://api.github.com/repos/Originate/git-town","forks_url":"https://api.github.com/repos/Originate/git-town/forks","keys_url":"https://api.github.com/repos/Originate/git-town/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Originate/git-town/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Originate/git-town/teams","hooks_url":"https://api.github.com/repos/Originate/git-town/hooks","issue_events_url":"https://api.github.com/repos/Originate/git-town/issues/events{/number}","events_url":"https://api.github.com/repos/Originate/git-town/events","assignees_url":"https://api.github.com/repos/Originate/git-town/assignees{/user}","branches_url":"https://api.github.com/repos/Originate/git-town/branches{/branch}","tags_url":"https://api.github.com/repos/Originate/git-town/tags","blobs_url":"https://api.github.com/repos/Originate/git-town/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Originate/git-town/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Originate/git-town/git/refs{/sha}","trees_url":"https://api.github.com/repos/Originate/git-town/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Originate/git-town/statuses/{sha}","languages_url":"https://api.github.com/repos/Originate/git-town/languages","stargazers_url":"https://api.github.com/repos/Originate/git-town/stargazers","contributors_url":"https://api.github.com/repos/Originate/git-town/contributors","subscribers_url":"https://api.github.com/repos/Originate/git-town/subscribers","subscription_url":"https://api.github.com/repos/Originate/git-town/subscription","commits_url":"https://api.github.com/repos/Originate/git-town/commits{/sha}","git_commits_url":"https://api.github.com/repos/Originate/git-town/git/commits{/sha}","comments_url":"https://api.github.com/repos/Originate/git-town/comments{/number}","issue_comment_url":"https://api.github.com/repos/Originate/git-town/issues/comments{/number}","contents_url":"https://api.github.com/repos/Originate/git-town/contents/{+path}","compare_url":"https://api.github.com/repos/Originate/git-town/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Originate/git-town/merges","archive_url":"https://api.github.com/repos/Originate/git-town/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Originate/git-town/downloads","issues_url":"https://api.github.com/repos/Originate/git-town/issues{/number}","pulls_url":"https://api.github.com/repos/Originate/git-town/pulls{/number}","milestones_url":"https://api.github.com/repos/Originate/git-town/milestones{/number}","notifications_url":"https://api.github.com/repos/Originate/git-town/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Originate/git-town/labels{/name}","releases_url":"https://api.github.com/repos/Originate/git-town/releases{/id}","created_at":"2014-05-15T15:44:29Z","updated_at":"2015-04-10T02:23:44Z","pushed_at":"2015-04-10T04:03:38Z","git_url":"git://github.com/Originate/git-town.git","ssh_url":"git@github.com:Originate/git-town.git","clone_url":"https://github.com/Originate/git-town.git","svn_url":"https://github.com/Originate/git-town","homepage":"","size":15773,"stargazers_count":46,"watchers_count":46,"language":"Cucumber","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":2,"mirror_url":null,"open_issues_count":51,"forks":2,"open_issues":51,"watchers":46,"default_branch":"master"}},"base":{"label":"Originate:master","ref":"master","sha":"d52802cd211f40e4966b598acc584c2abe326645","user":{"login":"Originate","id":1627168,"avatar_url":"https://avatars.githubusercontent.com/u/1627168?v=3","gravatar_id":"","url":"https://api.github.com/users/Originate","html_url":"https://github.com/Originate","followers_url":"https://api.github.com/users/Originate/followers","following_url":"https://api.github.com/users/Originate/following{/other_user}","gists_url":"https://api.github.com/users/Originate/gists{/gist_id}","starred_url":"https://api.github.com/users/Originate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Originate/subscriptions","organizations_url":"https://api.github.com/users/Originate/orgs","repos_url":"https://api.github.com/users/Originate/repos","events_url":"https://api.github.com/users/Originate/events{/privacy}","received_events_url":"https://api.github.com/users/Originate/received_events","type":"Organization","site_admin":false},"repo":{"id":19825320,"name":"git-town","full_name":"Originate/git-town","owner":{"login":"Originate","id":1627168,"avatar_url":"https://avatars.githubusercontent.com/u/1627168?v=3","gravatar_id":"","url":"https://api.github.com/users/Originate","html_url":"https://github.com/Originate","followers_url":"https://api.github.com/users/Originate/followers","following_url":"https://api.github.com/users/Originate/following{/other_user}","gists_url":"https://api.github.com/users/Originate/gists{/gist_id}","starred_url":"https://api.github.com/users/Originate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Originate/subscriptions","organizations_url":"https://api.github.com/users/Originate/orgs","repos_url":"https://api.github.com/users/Originate/repos","events_url":"https://api.github.com/users/Originate/events{/privacy}","received_events_url":"https://api.github.com/users/Originate/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Originate/git-town","description":"Git extensions for robust, high-level development workflows","fork":false,"url":"https://api.github.com/repos/Originate/git-town","forks_url":"https://api.github.com/repos/Originate/git-town/forks","keys_url":"https://api.github.com/repos/Originate/git-town/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Originate/git-town/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Originate/git-town/teams","hooks_url":"https://api.github.com/repos/Originate/git-town/hooks","issue_events_url":"https://api.github.com/repos/Originate/git-town/issues/events{/number}","events_url":"https://api.github.com/repos/Originate/git-town/events","assignees_url":"https://api.github.com/repos/Originate/git-town/assignees{/user}","branches_url":"https://api.github.com/repos/Originate/git-town/branches{/branch}","tags_url":"https://api.github.com/repos/Originate/git-town/tags","blobs_url":"https://api.github.com/repos/Originate/git-town/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Originate/git-town/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Originate/git-town/git/refs{/sha}","trees_url":"https://api.github.com/repos/Originate/git-town/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Originate/git-town/statuses/{sha}","languages_url":"https://api.github.com/repos/Originate/git-town/languages","stargazers_url":"https://api.github.com/repos/Originate/git-town/stargazers","contributors_url":"https://api.github.com/repos/Originate/git-town/contributors","subscribers_url":"https://api.github.com/repos/Originate/git-town/subscribers","subscription_url":"https://api.github.com/repos/Originate/git-town/subscription","commits_url":"https://api.github.com/repos/Originate/git-town/commits{/sha}","git_commits_url":"https://api.github.com/repos/Originate/git-town/git/commits{/sha}","comments_url":"https://api.github.com/repos/Originate/git-town/comments{/number}","issue_comment_url":"https://api.github.com/repos/Originate/git-town/issues/comments{/number}","contents_url":"https://api.github.com/repos/Originate/git-town/contents/{+path}","compare_url":"https://api.github.com/repos/Originate/git-town/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Originate/git-town/merges","archive_url":"https://api.github.com/repos/Originate/git-town/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Originate/git-town/downloads","issues_url":"https://api.github.com/repos/Originate/git-town/issues{/number}","pulls_url":"https://api.github.com/repos/Originate/git-town/pulls{/number}","milestones_url":"https://api.github.com/repos/Originate/git-town/milestones{/number}","notifications_url":"https://api.github.com/repos/Originate/git-town/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Originate/git-town/labels{/name}","releases_url":"https://api.github.com/repos/Originate/git-town/releases{/id}","created_at":"2014-05-15T15:44:29Z","updated_at":"2015-04-10T02:23:44Z","pushed_at":"2015-04-10T04:03:38Z","git_url":"git://github.com/Originate/git-town.git","ssh_url":"git@github.com:Originate/git-town.git","clone_url":"https://github.com/Originate/git-town.git","svn_url":"https://github.com/Originate/git-town","homepage":"","size":15773,"stargazers_count":46,"watchers_count":46,"language":"Cucumber","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":2,"mirror_url":null,"open_issues_count":51,"forks":2,"open_issues":51,"watchers":46,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Originate/git-town/pulls/483"},"html":{"href":"https://github.com/Originate/git-town/pull/483"},"issue":{"href":"https://api.github.com/repos/Originate/git-town/issues/483"},"comments":{"href":"https://api.github.com/repos/Originate/git-town/issues/483/comments"},"review_comments":{"href":"https://api.github.com/repos/Originate/git-town/pulls/483/comments"},"review_comment":{"href":"https://api.github.com/repos/Originate/git-town/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Originate/git-town/pulls/483/commits"},"statuses":{"href":"https://api.github.com/repos/Originate/git-town/statuses/6f5e354585e5beed842b6f95c48c7341c74fc50b"}}}}