txgh 5.3.4 → 5.4.0

Sign up to get free protection for your applications and to get access to all the features.
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