diff --git a/common/lib/dependabot/pull_request_creator.rb b/common/lib/dependabot/pull_request_creator.rb index 2aa94a2a6f7..8b35260afff 100644 --- a/common/lib/dependabot/pull_request_creator.rb +++ b/common/lib/dependabot/pull_request_creator.rb @@ -168,7 +168,8 @@ def initialize(cause, pull_request) ), dependency_group: T.nilable(Dependabot::DependencyGroup), pr_message_max_length: T.nilable(Integer), - pr_message_encoding: T.nilable(Encoding) + pr_message_encoding: T.nilable(Encoding), + draft: T::Boolean ) .void end @@ -183,7 +184,7 @@ def initialize(source:, base_commit:, dependencies:, files:, credentials:, github_redirection_service: DEFAULT_GITHUB_REDIRECTION_SERVICE, custom_headers: nil, require_up_to_date_base: false, provider_metadata: {}, message: nil, dependency_group: nil, pr_message_max_length: nil, - pr_message_encoding: nil) + pr_message_encoding: nil, draft: false) @dependencies = dependencies @source = source @base_commit = base_commit @@ -212,6 +213,7 @@ def initialize(source:, base_commit:, dependencies:, files:, credentials:, @dependency_group = dependency_group @pr_message_max_length = pr_message_max_length @pr_message_encoding = pr_message_encoding + @draft = draft check_dependencies_have_previous_version end @@ -257,6 +259,11 @@ def require_up_to_date_base? @require_up_to_date_base end + sig { returns(T::Boolean) } + def draft? + @draft + end + sig { returns(Dependabot::PullRequestCreator::Github) } def github_creator Github.new( @@ -275,7 +282,8 @@ def github_creator assignees: assignees, milestone: milestone, custom_headers: custom_headers, - require_up_to_date_base: require_up_to_date_base? + require_up_to_date_base: require_up_to_date_base?, + draft: draft? ) end diff --git a/common/lib/dependabot/pull_request_creator/github.rb b/common/lib/dependabot/pull_request_creator/github.rb index 262f25d2f1d..23378032283 100644 --- a/common/lib/dependabot/pull_request_creator/github.rb +++ b/common/lib/dependabot/pull_request_creator/github.rb @@ -20,13 +20,13 @@ class Github attr_reader :source, :branch_name, :base_commit, :credentials, :files, :pr_description, :pr_name, :commit_message, :author_details, :signature_key, :custom_headers, - :labeler, :reviewers, :assignees, :milestone + :labeler, :reviewers, :assignees, :milestone, :draft def initialize(source:, branch_name:, base_commit:, credentials:, files:, commit_message:, pr_description:, pr_name:, author_details:, signature_key:, custom_headers:, labeler:, reviewers:, assignees:, milestone:, - require_up_to_date_base:) + require_up_to_date_base:, draft:) @source = source @branch_name = branch_name @base_commit = base_commit @@ -43,6 +43,7 @@ def initialize(source:, branch_name:, base_commit:, credentials:, @assignees = assignees @milestone = milestone @require_up_to_date_base = require_up_to_date_base + @draft = draft end def create @@ -368,7 +369,10 @@ def create_pull_request branch_name, pr_name, pr_description, - headers: custom_headers || {} + { + headers: custom_headers || {}, + draft: draft + } ) rescue Octokit::UnprocessableEntity # Sometimes PR creation fails with no details (presumably because the diff --git a/common/spec/dependabot/config/file_spec.rb b/common/spec/dependabot/config/file_spec.rb index 75fabbe4771..7f7ee4772b1 100644 --- a/common/spec/dependabot/config/file_spec.rb +++ b/common/spec/dependabot/config/file_spec.rb @@ -17,6 +17,12 @@ expect { Dependabot::Config::File.parse("version: 1\n") } .to raise_error(Dependabot::Config::InvalidConfigError) end + + it "parses the config file with draft config" do + cfg = Dependabot::Config::File.parse(fixture("configfile", "bundler-weekly-draft.yml")) + expect(cfg.updates.size).to eq(1) + expect(cfg.updates.first[:draft]).to be_truthy + end end describe "File" do diff --git a/common/spec/dependabot/pull_request_creator/github_spec.rb b/common/spec/dependabot/pull_request_creator/github_spec.rb index d2b2aedda84..49a104f727f 100644 --- a/common/spec/dependabot/pull_request_creator/github_spec.rb +++ b/common/spec/dependabot/pull_request_creator/github_spec.rb @@ -24,7 +24,8 @@ reviewers: reviewers, assignees: assignees, milestone: milestone, - require_up_to_date_base: require_up_to_date_base + require_up_to_date_base: require_up_to_date_base, + draft: draft ) end @@ -52,6 +53,7 @@ let(:assignees) { nil } let(:milestone) { nil } let(:require_up_to_date_base) { false } + let(:draft) { false } let(:labeler) do Dependabot::PullRequestCreator::Labeler.new( source: source, @@ -437,7 +439,8 @@ base: "master", head: "randdependabot/bundler/business-1.5.0", title: "PR name", - body: "PR msg" + body: "PR msg", + draft: false } ) end @@ -455,7 +458,8 @@ base: "master", head: "randdependabot/bundler/business-1.5.0", title: "PR name", - body: "PR msg" + body: "PR msg", + draft: false }, headers: { "Accept" => "some-preview-header" } ) @@ -495,7 +499,8 @@ base: "master", head: "dependabot/bundler/business-1.5.0", title: "PR name", - body: "PR msg" + body: "PR msg", + draft: false } ) end @@ -573,7 +578,8 @@ base: "master", head: "dependabot/bundler/business-1.5.0", title: "PR name", - body: "PR msg" + body: "PR msg", + draft: false } ) end @@ -601,12 +607,40 @@ base: "master", head: "dependabot/bundler/business-1.5.0", title: "PR name", - body: "PR msg" + body: "PR msg", + draft: false } ) end end end + + context "when `draft` is true" do + let(:draft) { true } + + before do + stub_request(:post, "#{repo_api_url}/pulls") + .to_return(status: 200, + body: fixture("github", "create_draft_pr.json"), + headers: json_header) + end + + it "creates a PR" do + creator.create + + expect(WebMock) + .to have_requested(:post, "#{repo_api_url}/pulls") + .with( + body: { + base: "master", + head: "dependabot/bundler/business-1.5.0", + title: "PR name", + body: "PR msg", + draft: true + } + ) + end + end end end end @@ -640,7 +674,8 @@ base: "master", head: "dependabot/bundler/business-1.5.0", title: "PR name", - body: "PR msg" + body: "PR msg", + draft: false } ) end @@ -747,7 +782,8 @@ base: "master", head: "dependabot/bundler/business-1.5.0", title: "PR name", - body: "PR msg" + body: "PR msg", + draft: false } ) end @@ -785,7 +821,8 @@ base: "my_branch", head: "dependabot/bundler/my_branch/business-1.5.0", title: "PR name", - body: "PR msg" + body: "PR msg", + draft: false } ) end diff --git a/common/spec/dependabot/pull_request_creator_spec.rb b/common/spec/dependabot/pull_request_creator_spec.rb index c1de5dd6f5b..95bee540c24 100644 --- a/common/spec/dependabot/pull_request_creator_spec.rb +++ b/common/spec/dependabot/pull_request_creator_spec.rb @@ -203,7 +203,8 @@ reviewers: reviewers, assignees: assignees, milestone: milestone, - require_up_to_date_base: false + require_up_to_date_base: false, + draft: false ).and_return(dummy_creator) expect(dummy_creator).to receive(:create) creator.create @@ -365,7 +366,58 @@ require_up_to_date_base: false, pr_name: pr_name, pr_description: pr_message, - commit_message: commit_message + commit_message: commit_message, + draft: false + ).and_return(dummy_creator) + expect(dummy_creator).to receive(:create) + creator.create + end + end + + context "with a draft parameter" do + subject(:creator) do + described_class.new( + source: source, + base_commit: base_commit, + dependencies: dependencies, + files: files, + credentials: credentials, + custom_labels: custom_labels, + reviewers: reviewers, + assignees: assignees, + milestone: milestone, + author_details: author_details, + signature_key: signature_key, + provider_metadata: provider_metadata, + draft: draft + ) + end + + let(:draft) { true } + let(:source) { Dependabot::Source.new(provider: "github", repo: "gc/bp", branch: "main") } + let(:dummy_creator) { instance_double(described_class::Github) } + + it "delegates to PullRequestCreator::Github with correct params" do + expect(described_class::Github) + .to receive(:new) + .with( + source: source, + branch_name: "dependabot/bundler/main/business-1.5.0", + base_commit: base_commit, + credentials: credentials, + files: files, + commit_message: "Commit msg", + pr_description: "PR msg", + pr_name: "PR name", + author_details: author_details, + signature_key: signature_key, + custom_headers: nil, + labeler: instance_of(described_class::Labeler), + reviewers: reviewers, + assignees: assignees, + milestone: milestone, + require_up_to_date_base: false, + draft: true ).and_return(dummy_creator) expect(dummy_creator).to receive(:create) creator.create @@ -414,7 +466,8 @@ reviewers: reviewers, assignees: assignees, milestone: milestone, - require_up_to_date_base: false + require_up_to_date_base: false, + draft: false ).and_return(dummy_creator) expect(dummy_creator).to receive(:create) creator_with_group.create diff --git a/common/spec/fixtures/configfile/bundler-weekly-draft.yml b/common/spec/fixtures/configfile/bundler-weekly-draft.yml new file mode 100644 index 00000000000..435d9ff95b6 --- /dev/null +++ b/common/spec/fixtures/configfile/bundler-weekly-draft.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: "bundler" + directory: "/" + draft: true + schedule: + interval: "daily" diff --git a/common/spec/fixtures/github/create_draft_pr.json b/common/spec/fixtures/github/create_draft_pr.json new file mode 100644 index 00000000000..6064e26671e --- /dev/null +++ b/common/spec/fixtures/github/create_draft_pr.json @@ -0,0 +1,348 @@ +{ + "id": 1, + "url": "https://api.github.com/repos/gocardless/bump/pulls/1347", + "html_url": "https://github.com/gocardless/bump/pull/1347", + "diff_url": "https://github.com/gocardless/bump/pull/1347.diff", + "patch_url": "https://github.com/gocardless/bump/pull/1347.patch", + "issue_url": "https://api.github.com/repos/gocardless/bump/issues/1347", + "commits_url": "https://api.github.com/repos/gocardless/bump/pulls/1347/commits", + "review_comments_url": "https://api.github.com/repos/gocardless/bump/pulls/1347/comments", + "review_comment_url": "https://api.github.com/repos/gocardless/bump/pulls/comments/{number}", + "comments_url": "https://api.github.com/repos/gocardless/bump/issues/1347/comments", + "statuses_url": "https://api.github.com/repos/gocardless/bump/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "number": 1347, + "state": "open", + "title": "new-feature", + "body": "Please pull these awesome changes", + "draft": true, + "assignee": { + "login": "gocardless", + "id": 1, + "avatar_url": "https://github.com/images/error/gocardless_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/gocardless", + "html_url": "https://github.com/gocardless", + "followers_url": "https://api.github.com/users/gocardless/followers", + "following_url": "https://api.github.com/users/gocardless/following{/other_user}", + "gists_url": "https://api.github.com/users/gocardless/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gocardless/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gocardless/subscriptions", + "organizations_url": "https://api.github.com/users/gocardless/orgs", + "repos_url": "https://api.github.com/users/gocardless/repos", + "events_url": "https://api.github.com/users/gocardless/events{/privacy}", + "received_events_url": "https://api.github.com/users/gocardless/received_events", + "type": "User", + "site_admin": false + }, + "milestone": { + "url": "https://api.github.com/repos/gocardless/bump/milestones/1", + "html_url": "https://github.com/gocardless/bump/milestones/v1.0", + "labels_url": "https://api.github.com/repos/gocardless/bump/milestones/1/labels", + "id": 1002604, + "number": 1, + "state": "open", + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "creator": { + "login": "gocardless", + "id": 1, + "avatar_url": "https://github.com/images/error/gocardless_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/gocardless", + "html_url": "https://github.com/gocardless", + "followers_url": "https://api.github.com/users/gocardless/followers", + "following_url": "https://api.github.com/users/gocardless/following{/other_user}", + "gists_url": "https://api.github.com/users/gocardless/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gocardless/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gocardless/subscriptions", + "organizations_url": "https://api.github.com/users/gocardless/orgs", + "repos_url": "https://api.github.com/users/gocardless/repos", + "events_url": "https://api.github.com/users/gocardless/events{/privacy}", + "received_events_url": "https://api.github.com/users/gocardless/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 4, + "closed_issues": 8, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z", + "closed_at": "2013-02-12T13:22:01Z", + "due_on": "2012-10-09T23:39:01Z" + }, + "locked": false, + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:01:12Z", + "closed_at": "2011-01-26T19:01:12Z", + "merged_at": "2011-01-26T19:01:12Z", + "head": { + "label": "new-topic", + "ref": "new-topic", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": { + "login": "gocardless", + "id": 1, + "avatar_url": "https://github.com/images/error/gocardless_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/gocardless", + "html_url": "https://github.com/gocardless", + "followers_url": "https://api.github.com/users/gocardless/followers", + "following_url": "https://api.github.com/users/gocardless/following{/other_user}", + "gists_url": "https://api.github.com/users/gocardless/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gocardless/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gocardless/subscriptions", + "organizations_url": "https://api.github.com/users/gocardless/orgs", + "repos_url": "https://api.github.com/users/gocardless/repos", + "events_url": "https://api.github.com/users/gocardless/events{/privacy}", + "received_events_url": "https://api.github.com/users/gocardless/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 1296269, + "owner": { + "login": "gocardless", + "id": 1, + "avatar_url": "https://github.com/images/error/gocardless_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/gocardless", + "html_url": "https://github.com/gocardless", + "followers_url": "https://api.github.com/users/gocardless/followers", + "following_url": "https://api.github.com/users/gocardless/following{/other_user}", + "gists_url": "https://api.github.com/users/gocardless/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gocardless/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gocardless/subscriptions", + "organizations_url": "https://api.github.com/users/gocardless/orgs", + "repos_url": "https://api.github.com/users/gocardless/repos", + "events_url": "https://api.github.com/users/gocardless/events{/privacy}", + "received_events_url": "https://api.github.com/users/gocardless/received_events", + "type": "User", + "site_admin": false + }, + "name": "dependabot", + "full_name": "gocardless/bump", + "description": "This your first repo!", + "private": false, + "fork": false, + "url": "https://api.github.com/repos/gocardless/bump", + "html_url": "https://github.com/gocardless/bump", + "archive_url": "http://api.github.com/repos/gocardless/bump/{archive_format}{/ref}", + "assignees_url": "http://api.github.com/repos/gocardless/bump/assignees{/user}", + "blobs_url": "http://api.github.com/repos/gocardless/bump/git/blobs{/sha}", + "branches_url": "http://api.github.com/repos/gocardless/bump/branches{/branch}", + "clone_url": "https://github.com/gocardless/bump.git", + "collaborators_url": "http://api.github.com/repos/gocardless/bump/collaborators{/collaborator}", + "comments_url": "http://api.github.com/repos/gocardless/bump/comments{/number}", + "commits_url": "http://api.github.com/repos/gocardless/bump/commits{/sha}", + "compare_url": "http://api.github.com/repos/gocardless/bump/compare/{base}...{head}", + "contents_url": "http://api.github.com/repos/gocardless/bump/contents/{+path}", + "contributors_url": "http://api.github.com/repos/gocardless/bump/contributors", + "downloads_url": "http://api.github.com/repos/gocardless/bump/downloads", + "events_url": "http://api.github.com/repos/gocardless/bump/events", + "forks_url": "http://api.github.com/repos/gocardless/bump/forks", + "git_commits_url": "http://api.github.com/repos/gocardless/bump/git/commits{/sha}", + "git_refs_url": "http://api.github.com/repos/gocardless/bump/git/refs{/sha}", + "git_tags_url": "http://api.github.com/repos/gocardless/bump/git/tags{/sha}", + "git_url": "git:github.com/gocardless/bump.git", + "hooks_url": "http://api.github.com/repos/gocardless/bump/hooks", + "issue_comment_url": "http://api.github.com/repos/gocardless/bump/issues/comments{/number}", + "issue_events_url": "http://api.github.com/repos/gocardless/bump/issues/events{/number}", + "issues_url": "http://api.github.com/repos/gocardless/bump/issues{/number}", + "keys_url": "http://api.github.com/repos/gocardless/bump/keys{/key_id}", + "labels_url": "http://api.github.com/repos/gocardless/bump/labels{/name}", + "languages_url": "http://api.github.com/repos/gocardless/bump/languages", + "merges_url": "http://api.github.com/repos/gocardless/bump/merges", + "milestones_url": "http://api.github.com/repos/gocardless/bump/milestones{/number}", + "mirror_url": "git:git.example.com/gocardless/bump", + "notifications_url": "http://api.github.com/repos/gocardless/bump/notifications{?since, all, participating}", + "pulls_url": "http://api.github.com/repos/gocardless/bump/pulls{/number}", + "releases_url": "http://api.github.com/repos/gocardless/bump/releases{/id}", + "ssh_url": "git@github.com:gocardless/bump.git", + "stargazers_url": "http://api.github.com/repos/gocardless/bump/stargazers", + "statuses_url": "http://api.github.com/repos/gocardless/bump/statuses/{sha}", + "subscribers_url": "http://api.github.com/repos/gocardless/bump/subscribers", + "subscription_url": "http://api.github.com/repos/gocardless/bump/subscription", + "svn_url": "https://svn.github.com/gocardless/bump", + "tags_url": "http://api.github.com/repos/gocardless/bump/tags", + "teams_url": "http://api.github.com/repos/gocardless/bump/teams", + "trees_url": "http://api.github.com/repos/gocardless/bump/git/trees{/sha}", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "has_issues": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + } + } + }, + "base": { + "label": "master", + "ref": "master", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": { + "login": "gocardless", + "id": 1, + "avatar_url": "https://github.com/images/error/gocardless_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/gocardless", + "html_url": "https://github.com/gocardless", + "followers_url": "https://api.github.com/users/gocardless/followers", + "following_url": "https://api.github.com/users/gocardless/following{/other_user}", + "gists_url": "https://api.github.com/users/gocardless/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gocardless/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gocardless/subscriptions", + "organizations_url": "https://api.github.com/users/gocardless/orgs", + "repos_url": "https://api.github.com/users/gocardless/repos", + "events_url": "https://api.github.com/users/gocardless/events{/privacy}", + "received_events_url": "https://api.github.com/users/gocardless/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 1296269, + "owner": { + "login": "gocardless", + "id": 1, + "avatar_url": "https://github.com/images/error/gocardless_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/gocardless", + "html_url": "https://github.com/gocardless", + "followers_url": "https://api.github.com/users/gocardless/followers", + "following_url": "https://api.github.com/users/gocardless/following{/other_user}", + "gists_url": "https://api.github.com/users/gocardless/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gocardless/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gocardless/subscriptions", + "organizations_url": "https://api.github.com/users/gocardless/orgs", + "repos_url": "https://api.github.com/users/gocardless/repos", + "events_url": "https://api.github.com/users/gocardless/events{/privacy}", + "received_events_url": "https://api.github.com/users/gocardless/received_events", + "type": "User", + "site_admin": false + }, + "name": "dependabot", + "full_name": "gocardless/bump", + "description": "This your first repo!", + "private": false, + "fork": false, + "url": "https://api.github.com/repos/gocardless/bump", + "html_url": "https://github.com/gocardless/bump", + "archive_url": "http://api.github.com/repos/gocardless/bump/{archive_format}{/ref}", + "assignees_url": "http://api.github.com/repos/gocardless/bump/assignees{/user}", + "blobs_url": "http://api.github.com/repos/gocardless/bump/git/blobs{/sha}", + "branches_url": "http://api.github.com/repos/gocardless/bump/branches{/branch}", + "clone_url": "https://github.com/gocardless/bump.git", + "collaborators_url": "http://api.github.com/repos/gocardless/bump/collaborators{/collaborator}", + "comments_url": "http://api.github.com/repos/gocardless/bump/comments{/number}", + "commits_url": "http://api.github.com/repos/gocardless/bump/commits{/sha}", + "compare_url": "http://api.github.com/repos/gocardless/bump/compare/{base}...{head}", + "contents_url": "http://api.github.com/repos/gocardless/bump/contents/{+path}", + "contributors_url": "http://api.github.com/repos/gocardless/bump/contributors", + "downloads_url": "http://api.github.com/repos/gocardless/bump/downloads", + "events_url": "http://api.github.com/repos/gocardless/bump/events", + "forks_url": "http://api.github.com/repos/gocardless/bump/forks", + "git_commits_url": "http://api.github.com/repos/gocardless/bump/git/commits{/sha}", + "git_refs_url": "http://api.github.com/repos/gocardless/bump/git/refs{/sha}", + "git_tags_url": "http://api.github.com/repos/gocardless/bump/git/tags{/sha}", + "git_url": "git:github.com/gocardless/bump.git", + "hooks_url": "http://api.github.com/repos/gocardless/bump/hooks", + "issue_comment_url": "http://api.github.com/repos/gocardless/bump/issues/comments{/number}", + "issue_events_url": "http://api.github.com/repos/gocardless/bump/issues/events{/number}", + "issues_url": "http://api.github.com/repos/gocardless/bump/issues{/number}", + "keys_url": "http://api.github.com/repos/gocardless/bump/keys{/key_id}", + "labels_url": "http://api.github.com/repos/gocardless/bump/labels{/name}", + "languages_url": "http://api.github.com/repos/gocardless/bump/languages", + "merges_url": "http://api.github.com/repos/gocardless/bump/merges", + "milestones_url": "http://api.github.com/repos/gocardless/bump/milestones{/number}", + "mirror_url": "git:git.example.com/gocardless/bump", + "notifications_url": "http://api.github.com/repos/gocardless/bump/notifications{?since, all, participating}", + "pulls_url": "http://api.github.com/repos/gocardless/bump/pulls{/number}", + "releases_url": "http://api.github.com/repos/gocardless/bump/releases{/id}", + "ssh_url": "git@github.com:gocardless/bump.git", + "stargazers_url": "http://api.github.com/repos/gocardless/bump/stargazers", + "statuses_url": "http://api.github.com/repos/gocardless/bump/statuses/{sha}", + "subscribers_url": "http://api.github.com/repos/gocardless/bump/subscribers", + "subscription_url": "http://api.github.com/repos/gocardless/bump/subscription", + "svn_url": "https://svn.github.com/gocardless/bump", + "tags_url": "http://api.github.com/repos/gocardless/bump/tags", + "teams_url": "http://api.github.com/repos/gocardless/bump/teams", + "trees_url": "http://api.github.com/repos/gocardless/bump/git/trees{/sha}", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "has_issues": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + } + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/gocardless/bump/pulls/1347" + }, + "html": { + "href": "https://github.com/gocardless/bump/pull/1347" + }, + "issue": { + "href": "https://api.github.com/repos/gocardless/bump/issues/1347" + }, + "comments": { + "href": "https://api.github.com/repos/gocardless/bump/issues/1347/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/gocardless/bump/pulls/1347/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/gocardless/bump/pulls/comments/{number}" + }, + "commits": { + "href": "https://api.github.com/repos/gocardless/bump/pulls/1347/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/gocardless/bump/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e" + } + }, + "user": { + "login": "gocardless", + "id": 1, + "avatar_url": "https://github.com/images/error/gocardless_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/gocardless", + "html_url": "https://github.com/gocardless", + "followers_url": "https://api.github.com/users/gocardless/followers", + "following_url": "https://api.github.com/users/gocardless/following{/other_user}", + "gists_url": "https://api.github.com/users/gocardless/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gocardless/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gocardless/subscriptions", + "organizations_url": "https://api.github.com/users/gocardless/orgs", + "repos_url": "https://api.github.com/users/gocardless/repos", + "events_url": "https://api.github.com/users/gocardless/events{/privacy}", + "received_events_url": "https://api.github.com/users/gocardless/received_events", + "type": "User", + "site_admin": false + } +} \ No newline at end of file