danger-apkstats 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "apkstats/gem_version"
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "apkstats/plugin"
@@ -1,4 +1,6 @@
1
- require File.expand_path("../spec_helper", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path("spec_helper", __dir__)
2
4
 
3
5
  module Danger
4
6
  describe Danger::DangerApkstats do
@@ -16,31 +18,9 @@ module Danger
16
18
 
17
19
  # mock the PR data
18
20
  # you can then use this, eg. github.pr_author, later in the spec
19
- json = File.read(File.dirname(__FILE__) + '/support/fixtures/github_pr.json') # example json: `curl https://api.github.com/repos/danger/danger-plugin-template/pulls/18 > github_pr.json`
21
+ json = File.read(fixture_path + "github_pr.json")
20
22
  allow(@my_plugin.github).to receive(:pr_json).and_return(json)
21
23
  end
22
-
23
- # Some examples for writing tests
24
- # You should replace these with your own.
25
-
26
- it "Warns on a monday" do
27
- monday_date = Date.parse("2016-07-11")
28
- allow(Date).to receive(:today).and_return monday_date
29
-
30
- @my_plugin.warn_on_mondays
31
-
32
- expect(@dangerfile.status_report[:warnings]).to eq(["Trying to merge code on a Monday"])
33
- end
34
-
35
- it "Does nothing on a tuesday" do
36
- monday_date = Date.parse("2016-07-12")
37
- allow(Date).to receive(:today).and_return monday_date
38
-
39
- @my_plugin.warn_on_mondays
40
-
41
- expect(@dangerfile.status_report[:warnings]).to eq([])
42
- end
43
-
44
24
  end
45
25
  end
46
26
  end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../spec_helper"
4
+
5
+ module Apkstats::Command
6
+ describe Apkstats::Command::ApkAnalyzer do
7
+ let(:apk_base) { fixture_path + "app-base.apk" }
8
+ let(:apk_other1) { fixture_path + "app-other1.apk" }
9
+ let(:apk_other2) { fixture_path + "app-other2.apk" }
10
+ let(:apk_other3) { fixture_path + "app-other3.apk" }
11
+ let(:apk_other4) { fixture_path + "app-other4.apk" }
12
+ let(:apk_other5) { fixture_path + "app-other5.apk" }
13
+
14
+ it "should use custom path if set" do
15
+ expect(ApkAnalyzer.new({}).command_path).to eq("#{ENV.fetch('ANDROID_HOME')}/tools/bin/apkanalyzer")
16
+ expect(ApkAnalyzer.new(command_path: "/y/z").command_path).to eq("/y/z")
17
+ end
18
+
19
+ context "command" do
20
+ let(:command) { ApkAnalyzer.new({}) }
21
+
22
+ it "file_size should return apk size" do
23
+ expect(command.file_size(apk_base)).to eq(1_621_248.to_s)
24
+ end
25
+
26
+ it "download_size should return apk size for download" do
27
+ expect(command.download_size(apk_base)).to eq(1_308_587.to_s)
28
+ end
29
+
30
+ it "required_features should return features expect not-required features" do
31
+ features = command.required_features(apk_other1).values
32
+
33
+ expect(features).not_to be_empty
34
+ expect(features.any?(&:not_required?)).to be_falsey
35
+ end
36
+
37
+ it "non_required_features should return only not-required features" do
38
+ features = command.non_required_features(apk_other1).values
39
+
40
+ expect(features).not_to be_empty
41
+ expect(features.all?(&:not_required?)).to be_truthy
42
+ end
43
+
44
+ it "permissions should return features all permissions" do
45
+ permissions = command.permissions(apk_other4).values
46
+
47
+ expect(permissions).not_to be_empty
48
+ end
49
+
50
+ it "min_sdk should return min sdk" do
51
+ expect(command.min_sdk(apk_base)).to eq("15")
52
+ expect(command.min_sdk(apk_other5)).to eq("27")
53
+ end
54
+
55
+ it "target_sdk should return target sdk" do
56
+ expect(command.target_sdk(apk_base)).to eq("28")
57
+ end
58
+ end
59
+
60
+ context "to_permission" do
61
+ it "should return a permission without max_sdk" do
62
+ expect(
63
+ ApkAnalyzer.to_permission("android.permission.INTERNET")
64
+ ).to eq(::Apkstats::Entity::Permission.new("android.permission.INTERNET", max_sdk: nil))
65
+ end
66
+
67
+ it "should return a permission with max_sdk" do
68
+ expect(
69
+ ApkAnalyzer.to_permission("android.permission.INTERNET' maxSdkVersion='23")
70
+ ).to eq(::Apkstats::Entity::Permission.new("android.permission.INTERNET", max_sdk: "23"))
71
+ end
72
+ end
73
+
74
+ context "parse_permissions" do
75
+ it "should return each permissions" do
76
+ command_output = [
77
+ "android.permission.INTERNET",
78
+ "android.permission.INTERNET' maxSdkVersion='23"
79
+ ].join("\n")
80
+
81
+ expect(ApkAnalyzer.parse_permissions(command_output)).to contain_exactly(
82
+ ::Apkstats::Entity::Permission.new("android.permission.INTERNET", max_sdk: nil),
83
+ ::Apkstats::Entity::Permission.new("android.permission.INTERNET", max_sdk: "23")
84
+ )
85
+ end
86
+ end
87
+
88
+ context "parse_features" do
89
+ it "should return each features" do
90
+ command_output = [
91
+ "android.hardware.camera",
92
+ "android.hardware.faketouch not-required",
93
+ "android.hardware.camera implied: requested android.permission.CAMERA permission",
94
+ "android.hardware.faketouch implied: default feature for all apps",
95
+ ].join("\n")
96
+
97
+ expect(ApkAnalyzer.parse_features(command_output)).to contain_exactly(
98
+ ::Apkstats::Entity::Feature.new("android.hardware.camera", not_required: false, implied_reason: nil),
99
+ ::Apkstats::Entity::Feature.new("android.hardware.faketouch", not_required: true, implied_reason: nil),
100
+ ::Apkstats::Entity::Feature.new("android.hardware.camera", not_required: false, implied_reason: "requested android.permission.CAMERA permission"),
101
+ ::Apkstats::Entity::Feature.new("android.hardware.faketouch", not_required: false, implied_reason: "default feature for all apps")
102
+ )
103
+ end
104
+ end
105
+
106
+ context "to_feature" do
107
+ it "should return a feature" do
108
+ expect(
109
+ ApkAnalyzer.to_feature("android.hardware.camera")
110
+ ).to eq(::Apkstats::Entity::Feature.new("android.hardware.camera", not_required: false, implied_reason: nil))
111
+ end
112
+
113
+ it "should return a not-required feature" do
114
+ expect(
115
+ ApkAnalyzer.to_feature("android.hardware.faketouch not-required")
116
+ ).to eq(::Apkstats::Entity::Feature.new("android.hardware.faketouch", not_required: true, implied_reason: nil))
117
+ end
118
+
119
+ it "should return an implied feature" do
120
+ expect(
121
+ ApkAnalyzer.to_feature("android.hardware.camera implied: requested android.permission.CAMERA permission")
122
+ ).to eq(::Apkstats::Entity::Feature.new("android.hardware.camera", not_required: false, implied_reason: "requested android.permission.CAMERA permission"))
123
+
124
+ expect(
125
+ ApkAnalyzer.to_feature("android.hardware.faketouch implied: default feature for all apps")
126
+ ).to eq(::Apkstats::Entity::Feature.new("android.hardware.faketouch", not_required: false, implied_reason: "default feature for all apps"))
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../spec_helper"
4
+
5
+ module Apkstats::Entity
6
+ describe Apkstats::Entity::ApkInfoDiff do
7
+ def create_feature(name, opts = {})
8
+ Feature.new(name, not_required: opts[:not_required], implied_reason: opts[:implied_reason])
9
+ end
10
+
11
+ def create_permission(name, opts = {})
12
+ Permission.new(name, max_sdk: opts[:max_sdk])
13
+ end
14
+
15
+ let(:base_apk_values) do
16
+ {
17
+ file_size: 100,
18
+ download_size: 150,
19
+ required_features: Features.new([
20
+ create_feature("feature1"),
21
+ create_feature("feature2"),
22
+ create_feature("feature3", implied_reason: "implied_reason"),
23
+ ]),
24
+ non_required_features: Features.new([
25
+ create_feature("feature_1", not_required: true),
26
+ create_feature("feature_2", not_required: true),
27
+ ]),
28
+ permissions: Permissions.new([
29
+ create_permission("permission1"),
30
+ create_permission("permission2", max_sdk: "23"),
31
+ ]),
32
+ min_sdk: "16",
33
+ target_sdk: "26",
34
+ }
35
+ end
36
+
37
+ let(:other_apk_values) do
38
+ {
39
+ file_size: base_apk_values[:file_size] + 500,
40
+ download_size: base_apk_values[:download_size] - 100,
41
+ required_features: Features.new([
42
+ create_feature("feature1"),
43
+ create_feature("feature3"), # ignored
44
+ create_feature("feature4"),
45
+ # create_feature("feature2")
46
+ ]),
47
+ non_required_features: Features.new([
48
+ create_feature("feature_1", not_required: true),
49
+ create_feature("feature_3", not_required: true),
50
+ # create_feature("feature_2", not_required: true),
51
+ ]),
52
+ permissions: Permissions.new([
53
+ create_permission("permission1", max_sdk: "24"),
54
+ create_permission("permission2"),
55
+ # create_permission("permission1"),
56
+ # create_permission("permission2", "23"),
57
+ ]),
58
+ min_sdk: "21",
59
+ target_sdk: "27",
60
+ }
61
+ end
62
+
63
+ let(:base_command) { Apkstats::Stub::Command.new(base_apk_values) }
64
+ let(:other_command) { Apkstats::Stub::Command.new(other_apk_values) }
65
+
66
+ it "precondition for this spec" do
67
+ expect(base_apk_values).to include(*ApkInfo::KEYS)
68
+ expect(other_apk_values).to include(*ApkInfo::KEYS)
69
+ end
70
+
71
+ it "read values of a command" do
72
+ base_apk_info = ApkInfo.new(base_command, "apk filepath")
73
+ other_apk_info = ApkInfo.new(other_command, "apk filepath")
74
+
75
+ diff = ApkInfoDiff.new(base_apk_info, other_apk_info)
76
+
77
+ expect(diff.file_size).to eq(-500)
78
+ expect(diff.download_size).to eq(100)
79
+ expect(diff.required_features).to include(
80
+ new: Features.new([
81
+ create_feature("feature2"),
82
+ ]).to_a,
83
+ removed: Features.new([
84
+ create_feature("feature4"),
85
+
86
+ ]).to_a
87
+ )
88
+ expect(diff.non_required_features).to include(
89
+ new: Features.new([
90
+ create_feature("feature_2", not_required: true),
91
+ ]).to_a,
92
+ removed: Features.new([
93
+ create_feature("feature_3", not_required: true)
94
+ ]).to_a
95
+ )
96
+ expect(diff.permissions).to include(
97
+ new: Permissions.new([
98
+ create_permission("permission1"),
99
+ create_permission("permission2", max_sdk: "23"),
100
+ ]).to_a,
101
+ removed: Permissions.new([
102
+ create_permission("permission1", max_sdk: "24"),
103
+ create_permission("permission2"),
104
+ ]).to_a
105
+ )
106
+ expect(diff.min_sdk).to eq(%w(16 21))
107
+ expect(diff.target_sdk).to eq(%w(26 27))
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../spec_helper"
4
+
5
+ module Apkstats::Entity
6
+ describe Apkstats::Entity::ApkInfo do
7
+ let(:command_values) do
8
+ {
9
+ file_size: 100,
10
+ download_size: 150,
11
+ required_features: Features.new([
12
+ Feature.new("feature1"),
13
+ Feature.new("feature2"),
14
+ ]),
15
+ non_required_features: Features.new([
16
+ Feature.new("feature3", not_required: true),
17
+ Feature.new("feature4", not_required: true),
18
+ ]),
19
+ permissions: Permissions.new([
20
+ Permission.new("permission1"),
21
+ Permission.new("permission2", max_sdk: "23"),
22
+ ]),
23
+ min_sdk: "16",
24
+ target_sdk: "26",
25
+ }
26
+ end
27
+
28
+ let(:command) { Apkstats::Stub::Command.new(command_values) }
29
+
30
+ it "precondition for this spec" do
31
+ expect(command_values).to include(*ApkInfo::KEYS)
32
+ end
33
+
34
+ it "read values of a command" do
35
+ apk_info = ApkInfo.new(command, "apk filepath")
36
+
37
+ ApkInfo::KEYS.each do |key|
38
+ expect(apk_info.send(key)).to eq(command_values[key])
39
+ expect(apk_info[key]).to eq(command_values[key])
40
+ end
41
+ end
42
+
43
+ it "to_h" do
44
+ apk_info = ApkInfo.new(command, "apk filepath")
45
+
46
+ expect(apk_info.to_h).to include(command_values)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../spec_helper"
4
+
5
+ module Apkstats::Entity
6
+ describe Apkstats::Entity::Features do
7
+ def create_feature(name, opts = {})
8
+ Feature.new(name, not_required: opts[:not_required], implied_reason: opts[:implied_reason])
9
+ end
10
+
11
+ let(:feature1) { create_feature("feature1") }
12
+ let(:feature2) { create_feature("feature2", not_required: true) }
13
+ let(:feature3) { create_feature("feature3", implied_reason: "due to tests") }
14
+
15
+ context "-" do
16
+ it "should remove elements by name and not_required" do
17
+ one_two_three = Features.new([feature1, feature2, feature3])
18
+ one_two = Features.new([feature1, feature2])
19
+
20
+ expect((one_two_three - one_two).values).to contain_exactly(feature3)
21
+
22
+ new_feature2 = create_feature(feature2.name, not_required: !feature2.not_required?)
23
+ expect((one_two - Features.new([new_feature2])).values).to contain_exactly(feature1, feature2)
24
+
25
+ new_feature3 = create_feature(feature3.name, implied_reason: nil)
26
+ expect((one_two_three - Features.new([new_feature3])).values).to contain_exactly(feature1, feature2)
27
+ end
28
+ end
29
+
30
+ context "to_a" do
31
+ it "should return an array of stringified elements" do
32
+ one_two_three = Features.new([feature1, feature2, feature3])
33
+
34
+ expect(one_two_three.to_a).to contain_exactly(
35
+ feature1.to_s,
36
+ feature2.to_s,
37
+ feature3.to_s
38
+ )
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../spec_helper"
4
+
5
+ module Apkstats::Entity
6
+ describe Apkstats::Entity::Permissions do
7
+ def create_permission(name, opts = {})
8
+ Permission.new(name, max_sdk: opts[:max_sdk])
9
+ end
10
+
11
+ let(:permission1) { create_permission("permission1") }
12
+ let(:permission2) { create_permission("permission2", max_sdk: "24") }
13
+
14
+ context "-" do
15
+ it "should remove elements by name and max_sdk" do
16
+ one = Permissions.new([permission1])
17
+ one_two = Permissions.new([permission1, permission2])
18
+
19
+ expect((one_two - one).values).to contain_exactly(permission2)
20
+
21
+ new_permission2 = create_permission(permission2.name, max_sdk: "12")
22
+ expect((one_two - Permissions.new([new_permission2])).values).to contain_exactly(permission1, permission2)
23
+ end
24
+ end
25
+
26
+ context "to_a" do
27
+ it "should return an array of stringified elements" do
28
+ one_two = Permissions.new([permission1, permission2])
29
+
30
+ expect(one_two.to_a).to contain_exactly(
31
+ permission1.to_s,
32
+ permission2.to_s
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
Binary file
@@ -0,0 +1,345 @@
1
+ {
2
+ "url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls/1",
3
+ "id": 204049740,
4
+ "node_id": "MDExOlB1bGxSZXF1ZXN0MjA0MDQ5NzQw",
5
+ "html_url": "https://github.com/jmatsu/danger-apkstats-example/pull/1",
6
+ "diff_url": "https://github.com/jmatsu/danger-apkstats-example/pull/1.diff",
7
+ "patch_url": "https://github.com/jmatsu/danger-apkstats-example/pull/1.patch",
8
+ "issue_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues/1",
9
+ "number": 1,
10
+ "state": "open",
11
+ "locked": false,
12
+ "title": "Create README.md",
13
+ "user": {
14
+ "login": "jmatsu",
15
+ "id": 4340693,
16
+ "node_id": "MDQ6VXNlcjQzNDA2OTM=",
17
+ "avatar_url": "https://avatars0.githubusercontent.com/u/4340693?v=4",
18
+ "gravatar_id": "",
19
+ "url": "https://api.github.com/users/jmatsu",
20
+ "html_url": "https://github.com/jmatsu",
21
+ "followers_url": "https://api.github.com/users/jmatsu/followers",
22
+ "following_url": "https://api.github.com/users/jmatsu/following{/other_user}",
23
+ "gists_url": "https://api.github.com/users/jmatsu/gists{/gist_id}",
24
+ "starred_url": "https://api.github.com/users/jmatsu/starred{/owner}{/repo}",
25
+ "subscriptions_url": "https://api.github.com/users/jmatsu/subscriptions",
26
+ "organizations_url": "https://api.github.com/users/jmatsu/orgs",
27
+ "repos_url": "https://api.github.com/users/jmatsu/repos",
28
+ "events_url": "https://api.github.com/users/jmatsu/events{/privacy}",
29
+ "received_events_url": "https://api.github.com/users/jmatsu/received_events",
30
+ "type": "User",
31
+ "site_admin": false
32
+ },
33
+ "body": "",
34
+ "created_at": "2018-07-26T07:20:46Z",
35
+ "updated_at": "2018-07-26T07:20:46Z",
36
+ "closed_at": null,
37
+ "merged_at": null,
38
+ "merge_commit_sha": "0a529cc0d09524e7e1e416b4bf6d84b710f4d188",
39
+ "assignee": null,
40
+ "assignees": [
41
+
42
+ ],
43
+ "requested_reviewers": [
44
+
45
+ ],
46
+ "requested_teams": [
47
+
48
+ ],
49
+ "labels": [
50
+
51
+ ],
52
+ "milestone": null,
53
+ "commits_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls/1/commits",
54
+ "review_comments_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls/1/comments",
55
+ "review_comment_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls/comments{/number}",
56
+ "comments_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues/1/comments",
57
+ "statuses_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/statuses/3ead0ee040b70f29c4055ddfc3cc3d6a5c1445b0",
58
+ "head": {
59
+ "label": "jmatsu:jmatsu-patch-1",
60
+ "ref": "jmatsu-patch-1",
61
+ "sha": "3ead0ee040b70f29c4055ddfc3cc3d6a5c1445b0",
62
+ "user": {
63
+ "login": "jmatsu",
64
+ "id": 4340693,
65
+ "node_id": "MDQ6VXNlcjQzNDA2OTM=",
66
+ "avatar_url": "https://avatars0.githubusercontent.com/u/4340693?v=4",
67
+ "gravatar_id": "",
68
+ "url": "https://api.github.com/users/jmatsu",
69
+ "html_url": "https://github.com/jmatsu",
70
+ "followers_url": "https://api.github.com/users/jmatsu/followers",
71
+ "following_url": "https://api.github.com/users/jmatsu/following{/other_user}",
72
+ "gists_url": "https://api.github.com/users/jmatsu/gists{/gist_id}",
73
+ "starred_url": "https://api.github.com/users/jmatsu/starred{/owner}{/repo}",
74
+ "subscriptions_url": "https://api.github.com/users/jmatsu/subscriptions",
75
+ "organizations_url": "https://api.github.com/users/jmatsu/orgs",
76
+ "repos_url": "https://api.github.com/users/jmatsu/repos",
77
+ "events_url": "https://api.github.com/users/jmatsu/events{/privacy}",
78
+ "received_events_url": "https://api.github.com/users/jmatsu/received_events",
79
+ "type": "User",
80
+ "site_admin": false
81
+ },
82
+ "repo": {
83
+ "id": 142404092,
84
+ "node_id": "MDEwOlJlcG9zaXRvcnkxNDI0MDQwOTI=",
85
+ "name": "danger-apkstats-example",
86
+ "full_name": "jmatsu/danger-apkstats-example",
87
+ "owner": {
88
+ "login": "jmatsu",
89
+ "id": 4340693,
90
+ "node_id": "MDQ6VXNlcjQzNDA2OTM=",
91
+ "avatar_url": "https://avatars0.githubusercontent.com/u/4340693?v=4",
92
+ "gravatar_id": "",
93
+ "url": "https://api.github.com/users/jmatsu",
94
+ "html_url": "https://github.com/jmatsu",
95
+ "followers_url": "https://api.github.com/users/jmatsu/followers",
96
+ "following_url": "https://api.github.com/users/jmatsu/following{/other_user}",
97
+ "gists_url": "https://api.github.com/users/jmatsu/gists{/gist_id}",
98
+ "starred_url": "https://api.github.com/users/jmatsu/starred{/owner}{/repo}",
99
+ "subscriptions_url": "https://api.github.com/users/jmatsu/subscriptions",
100
+ "organizations_url": "https://api.github.com/users/jmatsu/orgs",
101
+ "repos_url": "https://api.github.com/users/jmatsu/repos",
102
+ "events_url": "https://api.github.com/users/jmatsu/events{/privacy}",
103
+ "received_events_url": "https://api.github.com/users/jmatsu/received_events",
104
+ "type": "User",
105
+ "site_admin": false
106
+ },
107
+ "private": true,
108
+ "html_url": "https://github.com/jmatsu/danger-apkstats-example",
109
+ "description": null,
110
+ "fork": false,
111
+ "url": "https://api.github.com/repos/jmatsu/danger-apkstats-example",
112
+ "forks_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/forks",
113
+ "keys_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/keys{/key_id}",
114
+ "collaborators_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/collaborators{/collaborator}",
115
+ "teams_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/teams",
116
+ "hooks_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/hooks",
117
+ "issue_events_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues/events{/number}",
118
+ "events_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/events",
119
+ "assignees_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/assignees{/user}",
120
+ "branches_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/branches{/branch}",
121
+ "tags_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/tags",
122
+ "blobs_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/blobs{/sha}",
123
+ "git_tags_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/tags{/sha}",
124
+ "git_refs_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/refs{/sha}",
125
+ "trees_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/trees{/sha}",
126
+ "statuses_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/statuses/{sha}",
127
+ "languages_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/languages",
128
+ "stargazers_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/stargazers",
129
+ "contributors_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/contributors",
130
+ "subscribers_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/subscribers",
131
+ "subscription_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/subscription",
132
+ "commits_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/commits{/sha}",
133
+ "git_commits_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/commits{/sha}",
134
+ "comments_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/comments{/number}",
135
+ "issue_comment_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues/comments{/number}",
136
+ "contents_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/contents/{+path}",
137
+ "compare_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/compare/{base}...{head}",
138
+ "merges_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/merges",
139
+ "archive_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/{archive_format}{/ref}",
140
+ "downloads_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/downloads",
141
+ "issues_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues{/number}",
142
+ "pulls_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls{/number}",
143
+ "milestones_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/milestones{/number}",
144
+ "notifications_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/notifications{?since,all,participating}",
145
+ "labels_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/labels{/name}",
146
+ "releases_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/releases{/id}",
147
+ "deployments_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/deployments",
148
+ "created_at": "2018-07-26T07:20:33Z",
149
+ "updated_at": "2018-07-26T07:20:36Z",
150
+ "pushed_at": "2018-07-26T07:20:46Z",
151
+ "git_url": "git://github.com/jmatsu/danger-apkstats-example.git",
152
+ "ssh_url": "git@github.com:jmatsu/danger-apkstats-example.git",
153
+ "clone_url": "https://github.com/jmatsu/danger-apkstats-example.git",
154
+ "svn_url": "https://github.com/jmatsu/danger-apkstats-example",
155
+ "homepage": null,
156
+ "size": 5,
157
+ "stargazers_count": 0,
158
+ "watchers_count": 0,
159
+ "language": null,
160
+ "has_issues": true,
161
+ "has_projects": true,
162
+ "has_downloads": true,
163
+ "has_wiki": true,
164
+ "has_pages": false,
165
+ "forks_count": 0,
166
+ "mirror_url": null,
167
+ "archived": false,
168
+ "open_issues_count": 1,
169
+ "license": {
170
+ "key": "apache-2.0",
171
+ "name": "Apache License 2.0",
172
+ "spdx_id": "Apache-2.0",
173
+ "url": "https://api.github.com/licenses/apache-2.0",
174
+ "node_id": "MDc6TGljZW5zZTI="
175
+ },
176
+ "forks": 0,
177
+ "open_issues": 1,
178
+ "watchers": 0,
179
+ "default_branch": "master"
180
+ }
181
+ },
182
+ "base": {
183
+ "label": "jmatsu:master",
184
+ "ref": "master",
185
+ "sha": "15c7f504cc25d69bbe1df1f2a31df874d3e4a3e9",
186
+ "user": {
187
+ "login": "jmatsu",
188
+ "id": 4340693,
189
+ "node_id": "MDQ6VXNlcjQzNDA2OTM=",
190
+ "avatar_url": "https://avatars0.githubusercontent.com/u/4340693?v=4",
191
+ "gravatar_id": "",
192
+ "url": "https://api.github.com/users/jmatsu",
193
+ "html_url": "https://github.com/jmatsu",
194
+ "followers_url": "https://api.github.com/users/jmatsu/followers",
195
+ "following_url": "https://api.github.com/users/jmatsu/following{/other_user}",
196
+ "gists_url": "https://api.github.com/users/jmatsu/gists{/gist_id}",
197
+ "starred_url": "https://api.github.com/users/jmatsu/starred{/owner}{/repo}",
198
+ "subscriptions_url": "https://api.github.com/users/jmatsu/subscriptions",
199
+ "organizations_url": "https://api.github.com/users/jmatsu/orgs",
200
+ "repos_url": "https://api.github.com/users/jmatsu/repos",
201
+ "events_url": "https://api.github.com/users/jmatsu/events{/privacy}",
202
+ "received_events_url": "https://api.github.com/users/jmatsu/received_events",
203
+ "type": "User",
204
+ "site_admin": false
205
+ },
206
+ "repo": {
207
+ "id": 142404092,
208
+ "node_id": "MDEwOlJlcG9zaXRvcnkxNDI0MDQwOTI=",
209
+ "name": "danger-apkstats-example",
210
+ "full_name": "jmatsu/danger-apkstats-example",
211
+ "owner": {
212
+ "login": "jmatsu",
213
+ "id": 4340693,
214
+ "node_id": "MDQ6VXNlcjQzNDA2OTM=",
215
+ "avatar_url": "https://avatars0.githubusercontent.com/u/4340693?v=4",
216
+ "gravatar_id": "",
217
+ "url": "https://api.github.com/users/jmatsu",
218
+ "html_url": "https://github.com/jmatsu",
219
+ "followers_url": "https://api.github.com/users/jmatsu/followers",
220
+ "following_url": "https://api.github.com/users/jmatsu/following{/other_user}",
221
+ "gists_url": "https://api.github.com/users/jmatsu/gists{/gist_id}",
222
+ "starred_url": "https://api.github.com/users/jmatsu/starred{/owner}{/repo}",
223
+ "subscriptions_url": "https://api.github.com/users/jmatsu/subscriptions",
224
+ "organizations_url": "https://api.github.com/users/jmatsu/orgs",
225
+ "repos_url": "https://api.github.com/users/jmatsu/repos",
226
+ "events_url": "https://api.github.com/users/jmatsu/events{/privacy}",
227
+ "received_events_url": "https://api.github.com/users/jmatsu/received_events",
228
+ "type": "User",
229
+ "site_admin": false
230
+ },
231
+ "private": true,
232
+ "html_url": "https://github.com/jmatsu/danger-apkstats-example",
233
+ "description": null,
234
+ "fork": false,
235
+ "url": "https://api.github.com/repos/jmatsu/danger-apkstats-example",
236
+ "forks_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/forks",
237
+ "keys_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/keys{/key_id}",
238
+ "collaborators_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/collaborators{/collaborator}",
239
+ "teams_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/teams",
240
+ "hooks_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/hooks",
241
+ "issue_events_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues/events{/number}",
242
+ "events_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/events",
243
+ "assignees_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/assignees{/user}",
244
+ "branches_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/branches{/branch}",
245
+ "tags_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/tags",
246
+ "blobs_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/blobs{/sha}",
247
+ "git_tags_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/tags{/sha}",
248
+ "git_refs_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/refs{/sha}",
249
+ "trees_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/trees{/sha}",
250
+ "statuses_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/statuses/{sha}",
251
+ "languages_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/languages",
252
+ "stargazers_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/stargazers",
253
+ "contributors_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/contributors",
254
+ "subscribers_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/subscribers",
255
+ "subscription_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/subscription",
256
+ "commits_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/commits{/sha}",
257
+ "git_commits_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/git/commits{/sha}",
258
+ "comments_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/comments{/number}",
259
+ "issue_comment_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues/comments{/number}",
260
+ "contents_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/contents/{+path}",
261
+ "compare_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/compare/{base}...{head}",
262
+ "merges_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/merges",
263
+ "archive_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/{archive_format}{/ref}",
264
+ "downloads_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/downloads",
265
+ "issues_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues{/number}",
266
+ "pulls_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls{/number}",
267
+ "milestones_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/milestones{/number}",
268
+ "notifications_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/notifications{?since,all,participating}",
269
+ "labels_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/labels{/name}",
270
+ "releases_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/releases{/id}",
271
+ "deployments_url": "https://api.github.com/repos/jmatsu/danger-apkstats-example/deployments",
272
+ "created_at": "2018-07-26T07:20:33Z",
273
+ "updated_at": "2018-07-26T07:20:36Z",
274
+ "pushed_at": "2018-07-26T07:20:46Z",
275
+ "git_url": "git://github.com/jmatsu/danger-apkstats-example.git",
276
+ "ssh_url": "git@github.com:jmatsu/danger-apkstats-example.git",
277
+ "clone_url": "https://github.com/jmatsu/danger-apkstats-example.git",
278
+ "svn_url": "https://github.com/jmatsu/danger-apkstats-example",
279
+ "homepage": null,
280
+ "size": 5,
281
+ "stargazers_count": 0,
282
+ "watchers_count": 0,
283
+ "language": null,
284
+ "has_issues": true,
285
+ "has_projects": true,
286
+ "has_downloads": true,
287
+ "has_wiki": true,
288
+ "has_pages": false,
289
+ "forks_count": 0,
290
+ "mirror_url": null,
291
+ "archived": false,
292
+ "open_issues_count": 1,
293
+ "license": {
294
+ "key": "apache-2.0",
295
+ "name": "Apache License 2.0",
296
+ "spdx_id": "Apache-2.0",
297
+ "url": "https://api.github.com/licenses/apache-2.0",
298
+ "node_id": "MDc6TGljZW5zZTI="
299
+ },
300
+ "forks": 0,
301
+ "open_issues": 1,
302
+ "watchers": 0,
303
+ "default_branch": "master"
304
+ }
305
+ },
306
+ "_links": {
307
+ "self": {
308
+ "href": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls/1"
309
+ },
310
+ "html": {
311
+ "href": "https://github.com/jmatsu/danger-apkstats-example/pull/1"
312
+ },
313
+ "issue": {
314
+ "href": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues/1"
315
+ },
316
+ "comments": {
317
+ "href": "https://api.github.com/repos/jmatsu/danger-apkstats-example/issues/1/comments"
318
+ },
319
+ "review_comments": {
320
+ "href": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls/1/comments"
321
+ },
322
+ "review_comment": {
323
+ "href": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls/comments{/number}"
324
+ },
325
+ "commits": {
326
+ "href": "https://api.github.com/repos/jmatsu/danger-apkstats-example/pulls/1/commits"
327
+ },
328
+ "statuses": {
329
+ "href": "https://api.github.com/repos/jmatsu/danger-apkstats-example/statuses/3ead0ee040b70f29c4055ddfc3cc3d6a5c1445b0"
330
+ }
331
+ },
332
+ "author_association": "OWNER",
333
+ "merged": false,
334
+ "mergeable": true,
335
+ "rebaseable": true,
336
+ "mergeable_state": "clean",
337
+ "merged_by": null,
338
+ "comments": 0,
339
+ "review_comments": 0,
340
+ "maintainer_can_modify": false,
341
+ "commits": 1,
342
+ "additions": 1,
343
+ "deletions": 0,
344
+ "changed_files": 1
345
+ }