txgh-server 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/lib/txgh-server/application.rb +141 -0
  3. data/lib/txgh-server/download_handler.rb +85 -0
  4. data/lib/txgh-server/github_request_auth.rb +28 -0
  5. data/lib/txgh-server/response.rb +15 -0
  6. data/lib/txgh-server/response_helpers.rb +26 -0
  7. data/lib/txgh-server/stream_response.rb +37 -0
  8. data/lib/txgh-server/tgz_stream_response.rb +39 -0
  9. data/lib/txgh-server/transifex_request_auth.rb +53 -0
  10. data/lib/txgh-server/triggers/handler.rb +50 -0
  11. data/lib/txgh-server/triggers/pull_handler.rb +18 -0
  12. data/lib/txgh-server/triggers/push_handler.rb +18 -0
  13. data/lib/txgh-server/triggers.rb +7 -0
  14. data/lib/txgh-server/version.rb +3 -0
  15. data/lib/txgh-server/webhooks/github/delete_handler.rb +37 -0
  16. data/lib/txgh-server/webhooks/github/handler.rb +20 -0
  17. data/lib/txgh-server/webhooks/github/ping_handler.rb +18 -0
  18. data/lib/txgh-server/webhooks/github/push_handler.rb +124 -0
  19. data/lib/txgh-server/webhooks/github/request_handler.rb +113 -0
  20. data/lib/txgh-server/webhooks/github.rb +11 -0
  21. data/lib/txgh-server/webhooks/transifex/hook_handler.rb +94 -0
  22. data/lib/txgh-server/webhooks/transifex/request_handler.rb +78 -0
  23. data/lib/txgh-server/webhooks/transifex.rb +8 -0
  24. data/lib/txgh-server/webhooks.rb +6 -0
  25. data/lib/txgh-server/zip_stream_response.rb +19 -0
  26. data/lib/txgh-server.rb +23 -0
  27. data/spec/application_spec.rb +347 -0
  28. data/spec/download_handler_spec.rb +91 -0
  29. data/spec/github_request_auth_spec.rb +39 -0
  30. data/spec/helpers/github_payload_builder.rb +141 -0
  31. data/spec/helpers/integration_setup.rb +47 -0
  32. data/spec/integration/cassettes/github_l10n_hook_endpoint.yml +536 -0
  33. data/spec/integration/cassettes/pull.yml +47 -0
  34. data/spec/integration/cassettes/push.yml +544 -0
  35. data/spec/integration/cassettes/transifex_hook_endpoint.yml +221 -0
  36. data/spec/integration/config/tx.config +10 -0
  37. data/spec/integration/hooks_spec.rb +159 -0
  38. data/spec/integration/payloads/github_postbody.json +161 -0
  39. data/spec/integration/payloads/github_postbody_l10n.json +136 -0
  40. data/spec/integration/payloads/github_postbody_release.json +136 -0
  41. data/spec/integration/triggers_spec.rb +45 -0
  42. data/spec/spec_helper.rb +26 -0
  43. data/spec/tgz_stream_response_spec.rb +59 -0
  44. data/spec/transifex_request_auth_spec.rb +39 -0
  45. data/spec/webhooks/github/delete_handler_spec.rb +38 -0
  46. data/spec/webhooks/github/ping_handler_spec.rb +16 -0
  47. data/spec/webhooks/github/push_handler_spec.rb +106 -0
  48. data/spec/webhooks/transifex/hook_handler_spec.rb +136 -0
  49. data/spec/zip_stream_response_spec.rb +58 -0
  50. data/txgh-server.gemspec +24 -0
  51. metadata +170 -0
@@ -0,0 +1,221 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://txgh.bot:<TRANSIFEX_PASSWORD>@www.transifex.com/api/2/project/test-project-88/resource/samplepo/translation/el_GR/
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.2
12
+ Accept:
13
+ - application/json
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Server:
22
+ - nginx
23
+ Date:
24
+ - Tue, 28 Jun 2016 22:05:59 GMT
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Vary:
32
+ - Accept-Encoding
33
+ - Authorization, Host, Accept-Language, Cookie
34
+ Content-Language:
35
+ - en
36
+ Expires:
37
+ - Tue, 28 Jun 2016 22:05:59 GMT
38
+ Last-Modified:
39
+ - Tue, 28 Jun 2016 22:05:59 GMT
40
+ Cache-Control:
41
+ - max-age=0
42
+ X-Frame-Options:
43
+ - SAMEORIGIN
44
+ X-Content-Type-Options:
45
+ - nosniff
46
+ body:
47
+ encoding: UTF-8
48
+ string: "{\n \"content\": \"# Translation file for Transifex.\\n# Copyright
49
+ (C) 2007-2010 Indifex Ltd.\\n# This file is distributed under the same license
50
+ as the Transifex package.\\n# \\n# Translators:\\n# Translators:\\nmsgid \\\"\\\"\\nmsgstr
51
+ \\\"\\\"\\n\\\"Project-Id-Version: test-project\\\\n\\\"\\n\\\"Report-Msgid-Bugs-To:
52
+ \\\\n\\\"\\n\\\"POT-Creation-Date: 2015-02-17 20:10+0000\\\\n\\\"\\n\\\"PO-Revision-Date:
53
+ 2016-01-19 19:08+0000\\\\n\\\"\\n\\\"Last-Translator: Ilias-Dimitrios Vrachnis\\\\n\\\"\\n\\\"Language-Team:
54
+ Greek (Greece) (http://www.transifex.com/txgh-test/test-project-88/language/el_GR/)\\\\n\\\"\\n\\\"MIME-Version:
55
+ 1.0\\\\n\\\"\\n\\\"Content-Type: text/plain; charset=UTF-8\\\\n\\\"\\n\\\"Content-Transfer-Encoding:
56
+ 8bit\\\\n\\\"\\n\\\"Language: el_GR\\\\n\\\"\\n\\\"Plural-Forms: nplurals=2;
57
+ plural=(n != 1);\\\\n\\\"\\n\\nmsgid \\\"One\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid
58
+ \\\"Two\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid \\\"Three\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid
59
+ \\\"Four\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid \\\"Five\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid
60
+ \\\"Six\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid \\\"Seven\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid
61
+ \\\"Eight\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid \\\"Nine\\\"\\nmsgstr \\\"\\\"\\n\\nmsgid
62
+ \\\"Ten\\\"\\nmsgstr \\\"\\\"\\n\", \n \"mimetype\": \"text/x-po\"\n}"
63
+ http_version:
64
+ recorded_at: Tue, 28 Jun 2016 22:05:59 GMT
65
+ - request:
66
+ method: get
67
+ uri: https://api.github.com/repos/txgh-bot/txgh-test-resources/contents/translations/el_GR/sample.po?ref=master
68
+ body:
69
+ encoding: US-ASCII
70
+ string: ''
71
+ headers:
72
+ Accept:
73
+ - application/vnd.github.v3+json
74
+ User-Agent:
75
+ - Octokit Ruby Gem 4.3.0
76
+ Content-Type:
77
+ - application/json
78
+ Authorization:
79
+ - token <GITHUB_TOKEN>
80
+ Accept-Encoding:
81
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
82
+ response:
83
+ status:
84
+ code: 200
85
+ message: OK
86
+ headers:
87
+ Server:
88
+ - GitHub.com
89
+ Date:
90
+ - Tue, 28 Jun 2016 22:05:59 GMT
91
+ Content-Type:
92
+ - application/json; charset=utf-8
93
+ Transfer-Encoding:
94
+ - chunked
95
+ Status:
96
+ - 200 OK
97
+ X-Ratelimit-Limit:
98
+ - '5000'
99
+ X-Ratelimit-Remaining:
100
+ - '4999'
101
+ X-Ratelimit-Reset:
102
+ - '1467155159'
103
+ Cache-Control:
104
+ - private, max-age=60, s-maxage=60
105
+ Vary:
106
+ - Accept, Authorization, Cookie, X-GitHub-OTP
107
+ - Accept-Encoding
108
+ Etag:
109
+ - W/"0c4897447f15f3dad309a5e63b994f66"
110
+ Last-Modified:
111
+ - Wed, 27 Apr 2016 17:33:49 GMT
112
+ X-Oauth-Scopes:
113
+ - public_repo
114
+ X-Accepted-Oauth-Scopes:
115
+ - ''
116
+ X-Github-Media-Type:
117
+ - github.v3; format=json
118
+ Access-Control-Expose-Headers:
119
+ - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
120
+ X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
121
+ Access-Control-Allow-Origin:
122
+ - "*"
123
+ Content-Security-Policy:
124
+ - default-src 'none'
125
+ Strict-Transport-Security:
126
+ - max-age=31536000; includeSubdomains; preload
127
+ X-Content-Type-Options:
128
+ - nosniff
129
+ X-Frame-Options:
130
+ - deny
131
+ X-Xss-Protection:
132
+ - 1; mode=block
133
+ X-Served-By:
134
+ - 593010132f82159af0ded24b4932e109
135
+ X-Github-Request-Id:
136
+ - 6171B7B3:3981:20641D9:5772F4C7
137
+ body:
138
+ encoding: UTF-8
139
+ string: '{"name":"sample.po","path":"translations/el_GR/sample.po","sha":"540a3d944ac19f573e756de687c8c4f3f9847b53","size":911,"url":"https://api.github.com/repos/txgh-bot/txgh-test-resources/contents/translations/el_GR/sample.po?ref=master","html_url":"https://github.com/txgh-bot/txgh-test-resources/blob/master/translations/el_GR/sample.po","git_url":"https://api.github.com/repos/txgh-bot/txgh-test-resources/git/blobs/540a3d944ac19f573e756de687c8c4f3f9847b53","download_url":"https://raw.githubusercontent.com/txgh-bot/txgh-test-resources/master/translations/el_GR/sample.po","type":"file","content":"IyBUcmFuc2xhdGlvbiBmaWxlIGZvciBUcmFuc2lmZXguCiMgQ29weXJpZ2h0\nIChDKSAyMDA3LTIwMTAgSW5kaWZleCBMdGQuCiMgVGhpcyBmaWxlIGlzIGRp\nc3RyaWJ1dGVkIHVuZGVyIHRoZSBzYW1lIGxpY2Vuc2UgYXMgdGhlIFRyYW5z\naWZleCBwYWNrYWdlLgojIAojIFRyYW5zbGF0b3JzOgojIFRyYW5zbGF0b3Jz\nOgptc2dpZCAiIgptc2dzdHIgIiIKIlByb2plY3QtSWQtVmVyc2lvbjogdGVz\ndC1wcm9qZWN0XG4iCiJSZXBvcnQtTXNnaWQtQnVncy1UbzogXG4iCiJQT1Qt\nQ3JlYXRpb24tRGF0ZTogMjAxNS0wMi0xNyAyMDoxMCswMDAwXG4iCiJQTy1S\nZXZpc2lvbi1EYXRlOiAyMDE2LTAxLTE5IDE5OjA4KzAwMDBcbiIKIkxhc3Qt\nVHJhbnNsYXRvcjogSWxpYXMtRGltaXRyaW9zIFZyYWNobmlzXG4iCiJMYW5n\ndWFnZS1UZWFtOiBHcmVlayAoR3JlZWNlKSAoaHR0cDovL3d3dy50cmFuc2lm\nZXguY29tL3R4Z2gtdGVzdC90ZXN0LXByb2plY3QtODgvbGFuZ3VhZ2UvZWxf\nR1IvKVxuIgoiTUlNRS1WZXJzaW9uOiAxLjBcbiIKIkNvbnRlbnQtVHlwZTog\ndGV4dC9wbGFpbjsgY2hhcnNldD1VVEYtOFxuIgoiQ29udGVudC1UcmFuc2Zl\nci1FbmNvZGluZzogOGJpdFxuIgoiTGFuZ3VhZ2U6IGVsX0dSXG4iCiJQbHVy\nYWwtRm9ybXM6IG5wbHVyYWxzPTI7IHBsdXJhbD0obiAhPSAxKTtcbiIKCm1z\nZ2lkICJPbmUiCm1zZ3N0ciAiIgoKbXNnaWQgIlR3byIKbXNnc3RyICIiCgpt\nc2dpZCAiVGhyZWUiCm1zZ3N0ciAiIgoKbXNnaWQgIkZvdXIiCm1zZ3N0ciAi\nIgoKbXNnaWQgIkZpdmUiCm1zZ3N0ciAiIgoKbXNnaWQgIlNpeCIKbXNnc3Ry\nICIiCgptc2dpZCAiU2V2ZW4iCm1zZ3N0ciAiIgoKbXNnaWQgIkVpZ2h0Igpt\nc2dzdHIgIiIKCm1zZ2lkICJOaW5lIgptc2dzdHIgIiIKCm1zZ2lkICJUZW4i\nCm1zZ3N0ciAiIgo=\n","encoding":"base64","_links":{"self":"https://api.github.com/repos/txgh-bot/txgh-test-resources/contents/translations/el_GR/sample.po?ref=master","git":"https://api.github.com/repos/txgh-bot/txgh-test-resources/git/blobs/540a3d944ac19f573e756de687c8c4f3f9847b53","html":"https://github.com/txgh-bot/txgh-test-resources/blob/master/translations/el_GR/sample.po"}}'
140
+ http_version:
141
+ recorded_at: Tue, 28 Jun 2016 22:06:00 GMT
142
+ - request:
143
+ method: get
144
+ uri: https://api.github.com/repos/txgh-bot/txgh-test-resources/git/refs/heads/master
145
+ body:
146
+ encoding: US-ASCII
147
+ string: ''
148
+ headers:
149
+ Accept:
150
+ - application/vnd.github.v3+json
151
+ User-Agent:
152
+ - Octokit Ruby Gem 4.3.0
153
+ Content-Type:
154
+ - application/json
155
+ Authorization:
156
+ - token <GITHUB_TOKEN>
157
+ Accept-Encoding:
158
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
159
+ response:
160
+ status:
161
+ code: 200
162
+ message: OK
163
+ headers:
164
+ Server:
165
+ - GitHub.com
166
+ Date:
167
+ - Tue, 28 Jun 2016 22:06:00 GMT
168
+ Content-Type:
169
+ - application/json; charset=utf-8
170
+ Transfer-Encoding:
171
+ - chunked
172
+ Status:
173
+ - 200 OK
174
+ X-Ratelimit-Limit:
175
+ - '5000'
176
+ X-Ratelimit-Remaining:
177
+ - '4998'
178
+ X-Ratelimit-Reset:
179
+ - '1467155159'
180
+ Cache-Control:
181
+ - private, max-age=60, s-maxage=60
182
+ Vary:
183
+ - Accept, Authorization, Cookie, X-GitHub-OTP
184
+ - Accept-Encoding
185
+ Etag:
186
+ - W/"a5fe675407899fa4460005cce07b9fe2"
187
+ Last-Modified:
188
+ - Mon, 11 Jan 2016 23:45:43 GMT
189
+ X-Poll-Interval:
190
+ - '300'
191
+ X-Oauth-Scopes:
192
+ - public_repo
193
+ X-Accepted-Oauth-Scopes:
194
+ - ''
195
+ X-Github-Media-Type:
196
+ - github.v3; format=json
197
+ Access-Control-Expose-Headers:
198
+ - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
199
+ X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
200
+ Access-Control-Allow-Origin:
201
+ - "*"
202
+ Content-Security-Policy:
203
+ - default-src 'none'
204
+ Strict-Transport-Security:
205
+ - max-age=31536000; includeSubdomains; preload
206
+ X-Content-Type-Options:
207
+ - nosniff
208
+ X-Frame-Options:
209
+ - deny
210
+ X-Xss-Protection:
211
+ - 1; mode=block
212
+ X-Served-By:
213
+ - a30e6f9aa7cf5731b87dfb3b9992202d
214
+ X-Github-Request-Id:
215
+ - 6171B7B3:3986:319BFEC:5772F4C8
216
+ body:
217
+ encoding: UTF-8
218
+ string: '{"ref":"refs/heads/master","url":"https://api.github.com/repos/txgh-bot/txgh-test-resources/git/refs/heads/master","object":{"sha":"f3edb21f027b70974750649ba29b0090e410ecde","type":"commit","url":"https://api.github.com/repos/txgh-bot/txgh-test-resources/git/commits/f3edb21f027b70974750649ba29b0090e410ecde"}}'
219
+ http_version:
220
+ recorded_at: Tue, 28 Jun 2016 22:06:00 GMT
221
+ recorded_with: VCR 3.0.1
@@ -0,0 +1,10 @@
1
+ [main]
2
+ host = https://www.transifex.com
3
+ lang_map =
4
+
5
+ # Create one such section per resource
6
+ [test-project-88.samplepo]
7
+ file_filter = translations/<lang>/sample.po
8
+ source_file = sample.po
9
+ source_lang = en
10
+ type = PO
@@ -0,0 +1,159 @@
1
+ require 'spec_helper'
2
+
3
+ require 'base64'
4
+ require 'json'
5
+ require 'pathname'
6
+ require 'rack/test'
7
+ require 'helpers/integration_setup'
8
+ require 'uri'
9
+ require 'yaml'
10
+
11
+ include Txgh
12
+
13
+ describe 'hook integration tests', integration: true do
14
+ include Rack::Test::Methods
15
+ include IntegrationSetup
16
+
17
+ def app
18
+ @app ||= TxghServer::WebhookEndpoints.new
19
+ end
20
+
21
+ around(:each) do |example|
22
+ Dir.chdir('./spec/integration') do
23
+ example.run
24
+ end
25
+ end
26
+
27
+ let(:base_config) do
28
+ {
29
+ 'github' => {
30
+ 'repos' => {
31
+ 'txgh-bot/txgh-test-resources' => {
32
+ 'api_username' => 'txgh-bot',
33
+ # github will auto-revoke a token if they notice it in one of your commits ;)
34
+ 'api_token' => Base64.decode64('YjViYWY3Nzk5NTdkMzVlMmI0OGZmYjk4YThlY2M1ZDY0NzAwNWRhZA=='),
35
+ 'push_source_to' => 'test-project-88',
36
+ 'branch' => 'master',
37
+ 'webhook_secret' => '18d3998f576dfe933357104b87abfd61'
38
+ }
39
+ }
40
+ },
41
+ 'transifex' => {
42
+ 'projects' => {
43
+ 'test-project-88' => {
44
+ 'tx_config' => 'file://./config/tx.config',
45
+ 'api_username' => 'txgh.bot',
46
+ 'api_password' => '2aqFGW99fPRKWvXBPjbrxkdiR',
47
+ 'push_translations_to' => 'txgh-bot/txgh-test-resources',
48
+ 'webhook_secret' => 'fce95b1748fd638c22174d34200f10cf',
49
+ 'languages' => ['el_GR']
50
+ }
51
+ }
52
+ }
53
+ }
54
+ end
55
+
56
+ before(:all) do
57
+ VCR.configure do |config|
58
+ config.filter_sensitive_data('<GITHUB_TOKEN>') do
59
+ base_config['github']['repos']['txgh-bot/txgh-test-resources']['api_token']
60
+ end
61
+
62
+ config.filter_sensitive_data('<TRANSIFEX_PASSWORD>') do
63
+ base_config['transifex']['projects']['test-project-88']['api_password']
64
+ end
65
+ end
66
+ end
67
+
68
+ before(:each) do
69
+ allow(Txgh::Config::KeyManager).to(
70
+ receive(:raw_config).and_return("raw://#{YAML.dump(base_config)}")
71
+ )
72
+ end
73
+
74
+ let(:payload_path) do
75
+ Pathname(File.dirname(__FILE__)).join('payloads')
76
+ end
77
+
78
+ let(:github_postbody) do
79
+ File.read(payload_path.join('github_postbody.json'))
80
+ end
81
+
82
+ let(:github_postbody_release) do
83
+ File.read(payload_path.join('github_postbody_release.json'))
84
+ end
85
+
86
+ let(:github_postbody_l10n) do
87
+ File.read(payload_path.join('github_postbody_l10n.json'))
88
+ end
89
+
90
+ let(:project_name) { 'test-project-88' }
91
+ let(:repo_name) { 'txgh-bot/txgh-test-resources' }
92
+
93
+ let(:config) do
94
+ Txgh::Config::KeyManager.config_from(project_name, repo_name)
95
+ end
96
+
97
+ def sign_github_request(body)
98
+ header(
99
+ GithubRequestAuth::GITHUB_HEADER,
100
+ GithubRequestAuth.header_value(body, config.github_repo.webhook_secret)
101
+ )
102
+ end
103
+
104
+ def sign_transifex_request(body)
105
+ header(
106
+ TransifexRequestAuth::TRANSIFEX_HEADER,
107
+ TransifexRequestAuth.header_value(body, config.transifex_project.webhook_secret)
108
+ )
109
+ end
110
+
111
+ it 'loads correct project config' do
112
+ expect(config.project_config).to_not be_nil
113
+ end
114
+
115
+ it 'verifies the transifex hook endpoint works' do
116
+ VCR.use_cassette('transifex_hook_endpoint') do
117
+ params = {
118
+ 'project' => 'test-project-88', 'resource' => 'samplepo',
119
+ 'language' => 'el_GR', 'translated' => 100
120
+ }
121
+
122
+ payload = URI.encode_www_form(params.to_a)
123
+
124
+ sign_transifex_request(payload)
125
+ post '/transifex', payload
126
+ expect(last_response).to be_ok
127
+ end
128
+ end
129
+
130
+ it 'verifies the github hook endpoint works' do
131
+ VCR.use_cassette('github_hook_endpoint') do
132
+ sign_github_request(github_postbody)
133
+ header 'X-GitHub-Event', 'push'
134
+ header 'content-type', 'application/x-www-form-urlencoded'
135
+ post '/github', github_postbody
136
+ expect(last_response).to be_ok
137
+ end
138
+ end
139
+
140
+ it 'verifies the github release hook endpoint works' do
141
+ VCR.use_cassette('github_release_hook_endpoint') do
142
+ sign_github_request(github_postbody_release)
143
+ header 'X-GitHub-Event', 'push'
144
+ header 'content-type', 'application/x-www-form-urlencoded'
145
+ post '/github', github_postbody_release
146
+ expect(last_response).to be_ok
147
+ end
148
+ end
149
+
150
+ it 'verifies the github l10n hook endpoint works' do
151
+ VCR.use_cassette('github_l10n_hook_endpoint') do
152
+ sign_github_request(github_postbody_l10n)
153
+ header 'X-GitHub-Event', 'push'
154
+ header 'content-type', 'application/x-www-form-urlencoded'
155
+ post '/github', github_postbody_l10n
156
+ expect(last_response).to be_ok
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,161 @@
1
+ {
2
+ "ref": "refs/heads/test",
3
+ "before": "0000000000000000000000000000000000000000",
4
+ "after": "fd2696fdb0c38d7a2bb4478b62423a701ad8f5fc",
5
+ "created": true,
6
+ "deleted": false,
7
+ "forced": true,
8
+ "base_ref": null,
9
+ "compare": "https://github.com/txgh-bot/txgh-test-resources/commit/fd2696fdb0c3",
10
+ "commits": [
11
+ {
12
+ "id": "fd2696fdb0c38d7a2bb4478b62423a701ad8f5fc",
13
+ "distinct": true,
14
+ "message": "Testing branch functionality",
15
+ "timestamp": "2015-10-10T22:03:14-07:00",
16
+ "url": "https://github.com/txgh-bot/txgh-test-resources/commit/fd2696fdb0c38d7a2bb4478b62423a701ad8f5fc",
17
+ "author": {
18
+ "name": "Txgh Bot",
19
+ "email": "txgh.bot@gmail.com",
20
+ "username": "txgh-bot"
21
+ },
22
+ "committer": {
23
+ "name": "Txgh Bot",
24
+ "email": "txgh.bot@gmail.com",
25
+ "username": "txgh-bot"
26
+ },
27
+ "added": [
28
+
29
+ ],
30
+ "removed": [
31
+
32
+ ],
33
+ "modified": [
34
+ "sample.po"
35
+ ]
36
+ }
37
+ ],
38
+ "head_commit": {
39
+ "id": "fd2696fdb0c38d7a2bb4478b62423a701ad8f5fc",
40
+ "distinct": true,
41
+ "message": "Testing branch functionality",
42
+ "timestamp": "2015-10-10T22:03:14-07:00",
43
+ "url": "https://github.com/txgh-bot/txgh-test-resources/commit/fd2696fdb0c38d7a2bb4478b62423a701ad8f5fc",
44
+ "author": {
45
+ "name": "Txgh Bot",
46
+ "email": "txgh.bot@gmail.com",
47
+ "username": "txgh-bot"
48
+ },
49
+ "committer": {
50
+ "name": "Txgh Bot",
51
+ "email": "txgh.bot@gmail.com",
52
+ "username": "txgh-bot"
53
+ },
54
+ "added": [
55
+
56
+ ],
57
+ "removed": [
58
+
59
+ ],
60
+ "modified": [
61
+ "sample.po"
62
+ ]
63
+ },
64
+ "repository": {
65
+ "id": 41740726,
66
+ "name": "txgh-test-resources",
67
+ "full_name": "txgh-bot/txgh-test-resources",
68
+ "owner": {
69
+ "name": "txgh-bot",
70
+ "email": "txgh.bot@gmail.com"
71
+ },
72
+ "private": false,
73
+ "html_url": "https://github.com/txgh-bot/txgh-test-resources",
74
+ "description": "Translation test repo for txgh",
75
+ "fork": false,
76
+ "url": "https://github.com/txgh-bot/txgh-test-resources",
77
+ "forks_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/forks",
78
+ "keys_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/keys{/key_id}",
79
+ "collaborators_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/collaborators{/collaborator}",
80
+ "teams_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/teams",
81
+ "hooks_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/hooks",
82
+ "issue_events_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/issues/events{/number}",
83
+ "events_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/events",
84
+ "assignees_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/assignees{/user}",
85
+ "branches_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/branches{/branch}",
86
+ "tags_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/tags",
87
+ "blobs_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/git/blobs{/sha}",
88
+ "git_tags_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/git/tags{/sha}",
89
+ "git_refs_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/git/refs{/sha}",
90
+ "trees_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/git/trees{/sha}",
91
+ "statuses_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/statuses/{sha}",
92
+ "languages_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/languages",
93
+ "stargazers_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/stargazers",
94
+ "contributors_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/contributors",
95
+ "subscribers_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/subscribers",
96
+ "subscription_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/subscription",
97
+ "commits_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/commits{/sha}",
98
+ "git_commits_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/git/commits{/sha}",
99
+ "comments_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/comments{/number}",
100
+ "issue_comment_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/issues/comments{/number}",
101
+ "contents_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/contents/{+path}",
102
+ "compare_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/compare/{base}...{head}",
103
+ "merges_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/merges",
104
+ "archive_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/{archive_format}{/ref}",
105
+ "downloads_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/downloads",
106
+ "issues_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/issues{/number}",
107
+ "pulls_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/pulls{/number}",
108
+ "milestones_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/milestones{/number}",
109
+ "notifications_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/notifications{?since,all,participating}",
110
+ "labels_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/labels{/name}",
111
+ "releases_url": "https://api.github.com/repos/txgh-bot/txgh-test-resources/releases{/id}",
112
+ "created_at": 1441114620,
113
+ "updated_at": "2015-09-01T13:37:00Z",
114
+ "pushed_at": 1444539817,
115
+ "git_url": "git://github.com/txgh-bot/txgh-test-resources.git",
116
+ "ssh_url": "git@github.com:txgh-bot/txgh-test-resources.git",
117
+ "clone_url": "https://github.com/txgh-bot/txgh-test-resources.git",
118
+ "svn_url": "https://github.com/txgh-bot/txgh-test-resources",
119
+ "homepage": null,
120
+ "size": 204,
121
+ "stargazers_count": 0,
122
+ "watchers_count": 0,
123
+ "language": null,
124
+ "has_issues": true,
125
+ "has_downloads": true,
126
+ "has_wiki": true,
127
+ "has_pages": false,
128
+ "forks_count": 0,
129
+ "mirror_url": null,
130
+ "open_issues_count": 0,
131
+ "forks": 0,
132
+ "open_issues": 0,
133
+ "watchers": 0,
134
+ "default_branch": "master",
135
+ "stargazers": 0,
136
+ "master_branch": "master"
137
+ },
138
+ "pusher": {
139
+ "name": "txgh-bot",
140
+ "email": "txgh.bot@gmail.com"
141
+ },
142
+ "sender": {
143
+ "login": "txgh-bot",
144
+ "id": 974299,
145
+ "avatar_url": "https://avatars.githubusercontent.com/u/974299?v=3",
146
+ "gravatar_id": "",
147
+ "url": "https://api.github.com/users/txgh-bot",
148
+ "html_url": "https://github.com/txgh-bot",
149
+ "followers_url": "https://api.github.com/users/txgh-bot/followers",
150
+ "following_url": "https://api.github.com/users/txgh-bot/following{/other_user}",
151
+ "gists_url": "https://api.github.com/users/txgh-bot/gists{/gist_id}",
152
+ "starred_url": "https://api.github.com/users/txgh-bot/starred{/owner}{/repo}",
153
+ "subscriptions_url": "https://api.github.com/users/txgh-bot/subscriptions",
154
+ "organizations_url": "https://api.github.com/users/txgh-bot/orgs",
155
+ "repos_url": "https://api.github.com/users/txgh-bot/repos",
156
+ "events_url": "https://api.github.com/users/txgh-bot/events{/privacy}",
157
+ "received_events_url": "https://api.github.com/users/txgh-bot/received_events",
158
+ "type": "User",
159
+ "site_admin": false
160
+ }
161
+ }