txgh 5.3.4 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/txgh/resource_deleter.rb +50 -0
  3. data/lib/txgh/version.rb +1 -1
  4. data/lib/txgh.rb +1 -6
  5. data/spec/resource_deleter_spec.rb +48 -0
  6. data/spec/spec_helper.rb +0 -8
  7. data/txgh.gemspec +1 -5
  8. metadata +6 -113
  9. data/lib/ext/zipline/output_stream.rb +0 -62
  10. data/lib/txgh/app.rb +0 -140
  11. data/lib/txgh/github_request_auth.rb +0 -28
  12. data/lib/txgh/handlers/download_handler.rb +0 -87
  13. data/lib/txgh/handlers/github/delete_handler.rb +0 -65
  14. data/lib/txgh/handlers/github/handler.rb +0 -20
  15. data/lib/txgh/handlers/github/ping_handler.rb +0 -18
  16. data/lib/txgh/handlers/github/push_handler.rb +0 -124
  17. data/lib/txgh/handlers/github/request_handler.rb +0 -113
  18. data/lib/txgh/handlers/github.rb +0 -11
  19. data/lib/txgh/handlers/response.rb +0 -17
  20. data/lib/txgh/handlers/stream_response.rb +0 -39
  21. data/lib/txgh/handlers/tgz_stream_response.rb +0 -41
  22. data/lib/txgh/handlers/transifex/hook_handler.rb +0 -94
  23. data/lib/txgh/handlers/transifex/request_handler.rb +0 -78
  24. data/lib/txgh/handlers/transifex.rb +0 -8
  25. data/lib/txgh/handlers/triggers/handler.rb +0 -52
  26. data/lib/txgh/handlers/triggers/pull_handler.rb +0 -20
  27. data/lib/txgh/handlers/triggers/push_handler.rb +0 -20
  28. data/lib/txgh/handlers/triggers.rb +0 -9
  29. data/lib/txgh/handlers/zip_stream_response.rb +0 -21
  30. data/lib/txgh/handlers.rb +0 -12
  31. data/lib/txgh/transifex_request_auth.rb +0 -53
  32. data/spec/app_spec.rb +0 -347
  33. data/spec/github_request_auth_spec.rb +0 -39
  34. data/spec/handlers/download_handler_spec.rb +0 -91
  35. data/spec/handlers/github/delete_handler_spec.rb +0 -71
  36. data/spec/handlers/github/ping_handler_spec.rb +0 -16
  37. data/spec/handlers/github/push_handler_spec.rb +0 -106
  38. data/spec/handlers/tgz_stream_response_spec.rb +0 -59
  39. data/spec/handlers/transifex/hook_handler_spec.rb +0 -136
  40. data/spec/handlers/zip_stream_response_spec.rb +0 -58
  41. data/spec/helpers/github_payload_builder.rb +0 -141
  42. data/spec/helpers/integration_setup.rb +0 -47
  43. data/spec/integration/cassettes/github_l10n_hook_endpoint.yml +0 -536
  44. data/spec/integration/cassettes/pull.yml +0 -47
  45. data/spec/integration/cassettes/push.yml +0 -544
  46. data/spec/integration/cassettes/transifex_hook_endpoint.yml +0 -221
  47. data/spec/integration/config/tx.config +0 -10
  48. data/spec/integration/hooks_spec.rb +0 -159
  49. data/spec/integration/payloads/github_postbody.json +0 -161
  50. data/spec/integration/payloads/github_postbody_l10n.json +0 -136
  51. data/spec/integration/payloads/github_postbody_release.json +0 -136
  52. data/spec/integration/triggers_spec.rb +0 -45
  53. data/spec/transifex_request_auth_spec.rb +0 -39
@@ -1,91 +0,0 @@
1
- require 'spec_helper'
2
- require 'helpers/standard_txgh_setup'
3
- require 'yaml'
4
-
5
- include Txgh::Handlers
6
-
7
- describe DownloadHandler do
8
- include StandardTxghSetup
9
-
10
- let(:format) { DownloadHandler::DEFAULT_FORMAT }
11
-
12
- let(:params) do
13
- {
14
- 'format' => format,
15
- 'project_slug' => project_name,
16
- 'branch' => ref
17
- }
18
- end
19
-
20
- context '.handle_request' do
21
- let(:request) do
22
- double(:request).tap do |dbl|
23
- allow(dbl).to receive(:params).and_return(params)
24
- allow(dbl).to receive(:env).and_return(env)
25
- end
26
- end
27
-
28
- let(:env) do
29
- { 'REQUEST_PATH' => "path/to/#{project_name}#{format}" }
30
- end
31
-
32
- it 'responds with a streaming zip and has the project name as the attachment' do
33
- response = DownloadHandler.handle_request(request)
34
- expect(response).to be_streaming
35
- expect(response).to be_a(ZipStreamResponse)
36
- expect(response.attachment).to eq(project_name)
37
- end
38
-
39
- context 'with a tgz format specified' do
40
- let(:format) { '.tgz' }
41
-
42
- it 'responds with a streaming tgz download' do
43
- response = DownloadHandler.handle_request(request)
44
- expect(response).to be_streaming
45
- expect(response).to be_a(TgzStreamResponse)
46
- end
47
- end
48
-
49
- context 'when an error occurs' do
50
- before(:each) do
51
- expect(request).to receive(:params).and_raise(StandardError)
52
- response = DownloadHandler.handle_request(request)
53
- expect(response).to_not be_streaming
54
- expect(response.status).to eq(500)
55
- end
56
- end
57
- end
58
-
59
- context '#execute' do
60
- let(:handler) do
61
- DownloadHandler.new(transifex_project, github_repo, params, logger)
62
- end
63
-
64
- it 'responds with a streaming zip download' do
65
- expect(handler.execute).to be_a(ZipStreamResponse)
66
- end
67
-
68
- it 'responds with the project name as the attachment' do
69
- response = handler.execute
70
- expect(response.attachment).to eq(project_name)
71
- end
72
-
73
- context 'with a tgz format specified' do
74
- let(:format) { '.tgz' }
75
-
76
- it 'responds with a streaming tgz download' do
77
- expect(handler.execute).to be_a(TgzStreamResponse)
78
- end
79
- end
80
-
81
- context 'with a set of languages' do
82
- let(:supported_languages) { %w(is fr) }
83
-
84
- it "downloads translations for the project's supported languages" do
85
- allow(transifex_api).to receive(:download)
86
- files = handler.execute.enum.to_a.map(&:first)
87
- expect(files).to eq(%w(translations/is/sample.yml translations/fr/sample.yml))
88
- end
89
- end
90
- end
91
- end
@@ -1,71 +0,0 @@
1
- require 'spec_helper'
2
- require 'helpers/github_payload_builder'
3
- require 'helpers/standard_txgh_setup'
4
-
5
- include Txgh
6
- include Txgh::Handlers::Github
7
-
8
- describe DeleteHandler do
9
- include StandardTxghSetup
10
-
11
- let(:handler) do
12
- DeleteHandler.new(
13
- project: transifex_project,
14
- repo: github_repo,
15
- payload: payload.to_h,
16
- logger: logger
17
- )
18
- end
19
-
20
- # process all branches
21
- let(:branch) { 'all' }
22
-
23
- let(:payload) do
24
- GithubPayloadBuilder.delete_payload(repo_name, ref)
25
- end
26
-
27
- let(:resource) { tx_config.resources.first }
28
-
29
- let(:resource_api_response) do
30
- [resource.to_api_h.merge('categories' => ["branch:#{ref}"])]
31
- end
32
-
33
- let(:resource_slug_with_branch) do
34
- "#{resource_slug}-#{Utils.slugify(ref)}"
35
- end
36
-
37
- it 'deletes the correct resource from transifex' do
38
- expect(transifex_api).to(
39
- receive(:get_resources).and_return(resource_api_response)
40
- )
41
-
42
- expect(transifex_api).to receive(:delete_resource) do |tx_resource|
43
- expect(tx_resource.project_slug).to eq(project_name)
44
- expect(tx_resource.resource_slug).to eq(resource_slug_with_branch)
45
- end
46
-
47
- response = handler.execute
48
- expect(response.status).to eq(200)
49
- expect(response.body).to eq(true)
50
- end
51
-
52
- it "does not delete resources that don't have a matching branch" do
53
- handler.payload['ref'] = 'heads/im_fake'
54
- expect(transifex_api).to(
55
- receive(:get_resources).and_return(resource_api_response)
56
- )
57
-
58
- expect(transifex_api).to_not receive(:delete)
59
- response = handler.execute
60
- expect(response.status).to eq(200)
61
- expect(response.body).to eq(true)
62
- end
63
-
64
- it 'does not delete resources if auto resource deletions are disabled' do
65
- project_config['auto_delete_resources'] = 'false'
66
- expect(transifex_api).to_not receive(:delete)
67
- response = handler.execute
68
- expect(response.status).to eq(200)
69
- expect(response.body).to eq(true)
70
- end
71
- end
@@ -1,16 +0,0 @@
1
- require 'spec_helper'
2
-
3
- include Txgh
4
- include Txgh::Handlers::Github
5
-
6
- describe PingHandler do
7
- let(:handler) do
8
- PingHandler.new
9
- end
10
-
11
- it 'responds with a 200 success' do
12
- response = handler.execute
13
- expect(response.status).to eq(200)
14
- expect(response.body).to eq({})
15
- end
16
- end
@@ -1,106 +0,0 @@
1
- require 'spec_helper'
2
- require 'helpers/github_payload_builder'
3
- require 'helpers/standard_txgh_setup'
4
-
5
- include Txgh
6
- include Txgh::Handlers::Github
7
-
8
- describe PushHandler do
9
- include StandardTxghSetup
10
-
11
- let(:handler) do
12
- PushHandler.new(
13
- project: transifex_project,
14
- repo: github_repo,
15
- payload: payload.to_h,
16
- logger: logger
17
- )
18
- end
19
-
20
- let(:payload) do
21
- GithubPayloadBuilder.push_payload(repo_name, ref)
22
- end
23
-
24
- let(:modified_files) do
25
- file_sha = 'def456'
26
- tx_config.resources.map do |resource|
27
- { 'path' => resource.source_file, 'sha' => file_sha.next! }
28
- end
29
- end
30
-
31
- let(:updater) { double(:updater) }
32
-
33
- before(:each) do
34
- payload.add_commit(
35
- modified: modified_files.map { |f| f['path'] }
36
- )
37
-
38
- allow(ResourceUpdater).to receive(:new).and_return(updater)
39
- end
40
-
41
- it 'correctly uploads modified resources to transifex' do
42
- tx_config.resources.each do |resource|
43
- expect(updater).to(
44
- receive(:update_resource) do |resource, sha, categories|
45
- expect(resource.project_slug).to eq(project_name)
46
- expect(resource.resource_slug).to eq(resource_slug)
47
- expect(sha).to eq(payload.head_commit[:id])
48
- expect(categories).to eq('author' => 'Test User')
49
- end
50
- )
51
-
52
- expect(github_api).to(
53
- receive(:get_ref).with(repo_name, ref).and_return(
54
- object: { sha: payload.head_commit[:id] }
55
- )
56
- )
57
- end
58
-
59
- response = handler.execute
60
- expect(response.status).to eq(200)
61
- expect(response.body).to eq(true)
62
- end
63
-
64
- context 'with an L10N branch' do
65
- let(:ref) { 'tags/L10N_my_branch' }
66
-
67
- it 'creates an L10N tag' do
68
- expect(updater).to receive(:update_resource)
69
-
70
- # this is what we actually care about in this test
71
- expect(github_api).to(
72
- receive(:create_ref).with(
73
- repo_name, 'heads/L10N', payload.head_commit[:id]
74
- )
75
- )
76
-
77
- expect(github_api).to(
78
- receive(:get_ref).with(repo_name, ref).and_return(
79
- object: { sha: payload.head_commit[:id] }
80
- )
81
- )
82
-
83
- response = handler.execute
84
- expect(response.status).to eq(200)
85
- expect(response.body).to eq(true)
86
- end
87
- end
88
-
89
- context 'with a deleted branch' do
90
- let(:before) { nil }
91
- let(:after) { '0' * 40 }
92
-
93
- let(:payload) do
94
- GithubPayloadBuilder.push_payload(repo_name, ref, before, after)
95
- end
96
-
97
- it "doesn't upload anything" do
98
- expect(updater).to_not receive(:update_resource)
99
- expect(github_api).to_not receive(:create_ref)
100
-
101
- response = handler.execute
102
- expect(response.status).to eq(200)
103
- expect(response.body).to eq(true)
104
- end
105
- end
106
- end
@@ -1,59 +0,0 @@
1
- require 'rubygems/package'
2
- require 'spec_helper'
3
- require 'stringio'
4
- require 'zlib'
5
-
6
- include Txgh::Handlers
7
-
8
- describe TgzStreamResponse do
9
- def read_tgz_from(io)
10
- contents = {}
11
-
12
- Zlib::GzipReader.wrap(io) do |gz|
13
- tar = Gem::Package::TarReader.new(gz)
14
- tar.each do |entry|
15
- contents[entry.full_name] = entry.read
16
- end
17
- end
18
-
19
- contents
20
- end
21
-
22
- let(:attachment) { 'abc123' }
23
-
24
- let(:enum) do
25
- {
26
- 'first_file.yml' => "first\nfile\ncontents\n",
27
- 'second_file.yml' => "wowowow\nanother file!\n"
28
- }
29
- end
30
-
31
- let(:response) do
32
- TgzStreamResponse.new(attachment, enum)
33
- end
34
-
35
- describe '#write_to' do
36
- it 'writes a gzipped tar file with the correct entries to the stream' do
37
- io = StringIO.new('', 'wb')
38
- response.write_to(io)
39
- io = io.reopen(io.string, 'rb')
40
- contents = read_tgz_from(io)
41
- expect(contents).to eq(enum)
42
- end
43
- end
44
-
45
- describe '#headers' do
46
- it 'includes the correct content type and disposition headers' do
47
- expect(response.headers).to eq({
48
- 'Content-Disposition' => "attachment; filename=\"#{attachment}.tgz\"",
49
- 'Content-Type' => 'application/x-gtar'
50
- })
51
- end
52
- end
53
-
54
- describe '#streaming?' do
55
- it 'returns true' do
56
- expect(response).to be_streaming
57
- end
58
- end
59
- end
@@ -1,136 +0,0 @@
1
- require 'spec_helper'
2
- require 'helpers/nil_logger'
3
- require 'helpers/standard_txgh_setup'
4
-
5
- include Txgh
6
- include Txgh::Handlers::Transifex
7
-
8
- describe HookHandler do
9
- include StandardTxghSetup
10
-
11
- let(:requested_resource_slug) do
12
- resource_slug
13
- end
14
-
15
- let(:handler) do
16
- HookHandler.new(
17
- project: transifex_project,
18
- repo: github_repo,
19
- resource_slug: requested_resource_slug,
20
- language: language,
21
- logger: logger
22
- )
23
- end
24
-
25
- let(:downloader) do
26
- instance_double(ResourceDownloader)
27
- end
28
-
29
- let(:file_name) do
30
- "translations/#{language}/sample.yml"
31
- end
32
-
33
- before(:each) do
34
- allow(ResourceDownloader).to receive(:new).and_return(downloader)
35
- allow(downloader).to(receive(:first)).and_return([
36
- "translations/#{language}/sample.yml", translations
37
- ])
38
-
39
- allow(github_api).to receive(:get_ref).and_return(
40
- object: { sha: '123abcshashasha' }
41
- )
42
- end
43
-
44
- it 'downloads translations and pushes them to the correct branch (head)' do
45
- expect(github_api).to(
46
- receive(:update_contents).with(
47
- repo_name, "heads/#{branch}",
48
- { "translations/#{language}/sample.yml" => translations },
49
- "Updating #{language} translations in #{file_name}"
50
- )
51
- )
52
-
53
- response = handler.execute
54
- expect(response.status).to eq(200)
55
- expect(response.body).to eq(true)
56
- end
57
-
58
- it "responds with an error if the config can't be found" do
59
- expect(handler).to receive(:tx_config).and_return(nil)
60
- response = handler.execute
61
- expect(response.status).to eq(404)
62
- expect(response.body).to eq([
63
- { error: "Could not find configuration for branch 'heads/#{branch}'" }
64
- ])
65
- end
66
-
67
- context 'with a non-existent resource' do
68
- let(:requested_resource_slug) { 'foobarbazboo' }
69
-
70
- it "responds with an error if the resource can't be found" do
71
- response = handler.execute
72
- expect(response.status).to eq(404)
73
- expect(response.body).to eq(
74
- [{ error: "Could not find resource '#{requested_resource_slug}' in config" }]
75
- )
76
- end
77
- end
78
-
79
- context 'when asked to process all branches' do
80
- let(:branch) { 'all' }
81
- let(:ref) { 'heads/my_branch' }
82
-
83
- let(:requested_resource_slug) do
84
- 'my_resource-heads_my_branch'
85
- end
86
-
87
- it 'pushes to the individual branch' do
88
- expect(transifex_api).to receive(:get_resource) do
89
- { 'categories' => ["branch:#{ref}"] }
90
- end
91
-
92
- expect(github_api).to(
93
- receive(:update_contents).with(
94
- repo_name, ref,
95
- { "translations/#{language}/sample.yml" => translations },
96
- "Updating #{language} translations in #{file_name}"
97
- )
98
- )
99
-
100
- response = handler.execute
101
- expect(response.status).to eq(200)
102
- expect(response.body).to eq(true)
103
- end
104
- end
105
-
106
- context 'with a tag instead of a branch' do
107
- let(:branch) { 'tags/my_tag' }
108
-
109
- it 'downloads translations and pushes them to the tag' do
110
- expect(github_api).to(
111
- receive(:update_contents).with(
112
- repo_name, "tags/my_tag",
113
- { "translations/#{language}/sample.yml" => translations },
114
- "Updating #{language} translations in #{file_name}"
115
- )
116
- )
117
-
118
- response = handler.execute
119
- expect(response.status).to eq(200)
120
- expect(response.body).to eq(true)
121
- end
122
- end
123
-
124
- context 'with an unsupported language' do
125
- let(:language) { 'pt' }
126
- let(:supported_languages) { ['ja'] }
127
-
128
- it "doesn't make a commit" do
129
- expect(github_api).to_not receive(:update_contents)
130
-
131
- response = handler.execute
132
- expect(response.status).to eq(304)
133
- expect(response.body).to eq(true)
134
- end
135
- end
136
- end
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
- require 'tempfile'
3
-
4
- include Txgh::Handlers
5
-
6
- describe ZipStreamResponse do
7
- def read_zip_from(file)
8
- contents = {}
9
-
10
- Zip::File.open(file) do |zipfile|
11
- zipfile.each do |entry|
12
- contents[entry.name] = entry.get_input_stream.read
13
- end
14
- end
15
-
16
- contents
17
- end
18
-
19
- let(:attachment) { 'abc123' }
20
-
21
- let(:enum) do
22
- {
23
- 'first_file.yml' => "first\nfile\ncontents\n",
24
- 'second_file.yml' => "wowowow\nanother file!\n"
25
- }
26
- end
27
-
28
- let(:response) do
29
- ZipStreamResponse.new(attachment, enum)
30
- end
31
-
32
- describe '#write_to' do
33
- it 'writes a zip file with the correct entries to the stream' do
34
- # this does NOT WORK with a StringIO - zip contents MUST be written to a file
35
- io = Tempfile.new('testzip')
36
- response.write_to(io)
37
- contents = read_zip_from(io.path)
38
- expect(contents).to eq(enum)
39
- io.close
40
- io.unlink
41
- end
42
- end
43
-
44
- describe '#headers' do
45
- it 'includes the correct content type and disposition headers' do
46
- expect(response.headers).to eq({
47
- 'Content-Disposition' => "attachment; filename=\"#{attachment}.zip\"",
48
- 'Content-Type' => 'application/zip'
49
- })
50
- end
51
- end
52
-
53
- describe '#streaming?' do
54
- it 'returns true' do
55
- expect(response).to be_streaming
56
- end
57
- end
58
- end
@@ -1,141 +0,0 @@
1
- require 'json'
2
-
3
- class GithubPayloadBuilder
4
- class << self
5
- def push_payload(*args)
6
- GithubPushPayload.new(*args)
7
- end
8
-
9
- def delete_payload(*args)
10
- GithubDeletePayload.new(*args)
11
- end
12
- end
13
- end
14
-
15
- class GithubPayload
16
- def to_h
17
- # convert symbolized keys to strings
18
- JSON.parse(to_json)
19
- end
20
-
21
- def to_json
22
- @result.to_json
23
- end
24
-
25
- protected
26
-
27
- def digits
28
- @@digits ||= ('a'..'f').to_a + ('0'..'9').to_a
29
- end
30
-
31
- def generate_timestamp
32
- Time.now.strftime('%Y-%m-%dT%H:%M:%S%:z')
33
- end
34
-
35
- def generate_sha
36
- blank_commit_id.gsub(/0/) { digits.sample }
37
- end
38
-
39
- def blank_commit_id
40
- '0' * 40
41
- end
42
- end
43
-
44
- class GithubDeletePayload < GithubPayload
45
- attr_reader :repo, :ref
46
-
47
- def initialize(repo, ref)
48
- @repo = repo
49
- @ref = ref
50
-
51
- @result = {
52
- ref: "refs/#{ref}",
53
- ref_type: 'branch',
54
- pusher_type: 'user',
55
-
56
- repository: {
57
- name: repo.split('/').last,
58
- full_name: repo,
59
- owner: {
60
- login: repo.split('/').first
61
- }
62
- },
63
-
64
- sender: {
65
- login: repo.split('/').first,
66
- type: 'User'
67
- }
68
- }
69
- end
70
- end
71
-
72
- class GithubPushPayload < GithubPayload
73
- attr_reader :repo, :ref, :before, :after
74
-
75
- DEFAULT_USER = {
76
- name: 'Test User',
77
- email: 'test@user.com',
78
- username: 'testuser'
79
- }
80
-
81
- def initialize(repo, ref, before = nil, after = nil)
82
- @repo = repo
83
- @ref = ref
84
- @before = before || blank_commit_id
85
- @after = after || generate_sha
86
-
87
- @result = {
88
- ref: "refs/#{ref}",
89
- before: @before,
90
- after: @after,
91
- created: true,
92
- deleted: false,
93
- forced: true,
94
- base_ref: nil,
95
- compare: "https://github.com/#{@repo}/commit/#{@after[0..12]}",
96
- commits: [],
97
- repository: {
98
- name: repo.split('/').last,
99
- full_name: repo,
100
- owner: {
101
- name: repo.split('/').first
102
- }
103
- }
104
- }
105
- end
106
-
107
- def add_commit(options = {})
108
- id = if commits.empty? && !options.include?(:id)
109
- after
110
- else
111
- options.fetch(:id) { generate_sha }
112
- end
113
-
114
- commit_data = {
115
- id: id,
116
- distinct: options.fetch(:distinct, true),
117
- message: options.fetch(:message, 'Default commit message'),
118
- timestamp: options.fetch(:timestamp) { generate_timestamp },
119
- url: "https://github.com/#{repo}/commit/#{id}",
120
- author: options.fetch(:author, DEFAULT_USER),
121
- committer: options.fetch(:committer, DEFAULT_USER),
122
- added: options.fetch(:added, []),
123
- removed: options.fetch(:removed, []),
124
- modified: options.fetch(:modified, [])
125
- }
126
-
127
- if commit_data[:id] == after
128
- @result[:head_commit] = commit_data
129
- end
130
-
131
- commits << commit_data
132
- end
133
-
134
- def commits
135
- @result[:commits]
136
- end
137
-
138
- def head_commit
139
- @result[:head_commit]
140
- end
141
- end