travis-backup 0.2.1 → 0.3.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/.gitignore +1 -0
  3. data/README.md +14 -4
  4. data/lib/backup/load_from_files.rb +245 -0
  5. data/lib/backup/remove_orphans.rb +81 -50
  6. data/lib/backup/remove_specified/remove_heavy_data.rb +99 -0
  7. data/lib/backup/remove_specified/remove_with_all_dependencies.rb +51 -0
  8. data/lib/backup/remove_specified/shared.rb +20 -0
  9. data/lib/backup/remove_specified.rb +68 -0
  10. data/lib/backup/save_file.rb +43 -0
  11. data/lib/backup/save_id_hash_to_file.rb +33 -0
  12. data/lib/backup/save_nullified_rels_to_file.rb +29 -0
  13. data/lib/config.rb +37 -7
  14. data/lib/dry_run_reporter.rb +18 -4
  15. data/lib/id_hash.rb +97 -0
  16. data/lib/ids_of_all_dependencies.rb +330 -0
  17. data/lib/model.rb +77 -0
  18. data/lib/models/abuse.rb +9 -0
  19. data/lib/models/annotation.rb +8 -0
  20. data/lib/models/branch.rb +9 -1
  21. data/lib/models/broadcast.rb +8 -0
  22. data/lib/models/build.rb +23 -3
  23. data/lib/models/commit.rb +8 -1
  24. data/lib/models/cron.rb +2 -1
  25. data/lib/models/email.rb +8 -0
  26. data/lib/models/invoice.rb +8 -0
  27. data/lib/models/job.rb +10 -2
  28. data/lib/models/log.rb +1 -1
  29. data/lib/models/membership.rb +9 -0
  30. data/lib/models/message.rb +8 -0
  31. data/lib/models/organization.rb +15 -1
  32. data/lib/models/owner_group.rb +8 -0
  33. data/lib/models/permission.rb +9 -0
  34. data/lib/models/pull_request.rb +5 -1
  35. data/lib/models/queueable_job.rb +8 -0
  36. data/lib/models/repository.rb +16 -3
  37. data/lib/models/request.rb +11 -1
  38. data/lib/models/ssl_key.rb +2 -1
  39. data/lib/models/stage.rb +4 -1
  40. data/lib/models/star.rb +9 -0
  41. data/lib/models/subscription.rb +9 -0
  42. data/lib/models/tag.rb +7 -1
  43. data/lib/models/token.rb +8 -0
  44. data/lib/models/trial.rb +9 -0
  45. data/lib/models/trial_allowance.rb +9 -0
  46. data/lib/models/user.rb +33 -1
  47. data/lib/models/user_beta_feature.rb +8 -0
  48. data/lib/nullify_dependencies.rb +42 -0
  49. data/lib/travis-backup.rb +29 -5
  50. data/travis-backup.gemspec +1 -1
  51. metadata +35 -9
  52. data/lib/backup/remove_old.rb +0 -204
  53. data/lib/models/model.rb +0 -8
@@ -1,10 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'models/model'
3
+ require 'model'
4
4
  require 'models/repository'
5
5
 
6
6
  class Request < Model
7
+ belongs_to :owner, polymorphic: true
8
+ belongs_to :sender, polymorphic: true
7
9
  belongs_to :repository
10
+ belongs_to :branch
11
+ belongs_to :pull_request
12
+ belongs_to :tag
13
+ belongs_to :commit
14
+ has_many :abuses
15
+ has_many :messages, as: :subject
16
+ has_many :jobs, as: :source
17
+ has_many :builds
8
18
 
9
19
  self.table_name = 'requests'
10
20
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'models/model'
3
+ require 'model'
4
4
 
5
5
  class SslKey < Model
6
+ belongs_to :repository
6
7
  self.table_name = 'ssl_keys'
7
8
  end
data/lib/models/stage.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'models/model'
3
+ require 'model'
4
4
 
5
5
  class Stage < Model
6
+ belongs_to :build
7
+ has_many :jobs
8
+
6
9
  self.table_name = 'stages'
7
10
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'model'
4
+
5
+ class Star < Model
6
+ belongs_to :repository
7
+ belongs_to :user
8
+ self.table_name = 'stars'
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'model'
4
+
5
+ class Subscription < Model
6
+ belongs_to :owner, polymorphic: true
7
+ has_many :invoices
8
+ self.table_name = 'subscriptions'
9
+ end
data/lib/models/tag.rb CHANGED
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'models/model'
3
+ require 'model'
4
4
 
5
5
  class Tag < Model
6
+ belongs_to :last_build, foreign_key: :last_build_id, class_name: 'Build'
7
+ belongs_to :repository
8
+ has_many :builds
9
+ has_many :commits
10
+ has_many :requests
11
+
6
12
  self.table_name = 'tags'
7
13
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'model'
4
+
5
+ class Token < Model
6
+ belongs_to :user
7
+ self.table_name = 'tokens'
8
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'model'
4
+
5
+ class Trial < Model
6
+ belongs_to :owner, polymorphic: true
7
+ has_many :trial_allowances
8
+ self.table_name = 'trials'
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'model'
4
+
5
+ class TrialAllowance < Model
6
+ belongs_to :creator, polymorphic: true
7
+ belongs_to :trial
8
+ self.table_name = 'trial_allowances'
9
+ end
data/lib/models/user.rb CHANGED
@@ -1,7 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'models/model'
3
+ require 'model'
4
+ require 'models/abuse'
5
+ require 'models/subscription'
6
+ require 'models/owner_group'
7
+ require 'models/trial'
8
+ require 'models/trial_allowance'
9
+ require 'models/broadcast'
10
+ require 'models/star'
11
+ require 'models/permission'
12
+ require 'models/token'
13
+ require 'models/email'
14
+ require 'models/membership'
15
+ require 'models/user_beta_feature'
4
16
 
5
17
  class User < Model
18
+ has_many :builds_for_that_this_user_is_owner, as: :owner, class_name: 'Build'
19
+ has_many :builds_for_that_this_user_is_sender, as: :sender, class_name: 'Build'
20
+ has_many :repositories, as: :owner
21
+ has_many :jobs, as: :owner
22
+ has_many :requests_for_that_this_user_is_owner, as: :owner, class_name: 'Request'
23
+ has_many :abuses, as: :owner
24
+ has_many :subscriptions, as: :owner
25
+ has_many :owner_groups, as: :owner
26
+ has_many :trials, as: :owner
27
+ has_many :trial_allowances, as: :creator
28
+ has_many :broadcasts, as: :recipient
29
+ has_many :requests_for_that_this_user_is_sender, as: :sender, class_name: 'Request'
30
+
31
+ has_many :stars
32
+ has_many :permissions
33
+ has_many :tokens
34
+ has_many :emails
35
+ has_many :memberships
36
+ has_many :user_beta_features
37
+
6
38
  self.table_name = 'users'
7
39
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'model'
4
+
5
+ class UserBetaFeature < Model
6
+ belongs_to :user
7
+ self.table_name = 'user_beta_features'
8
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NullifyDependencies
4
+ def nullify_dependencies(dependencies_symbols_to_nullify)
5
+ dependencies_symbols_to_nullify.map do |symbol|
6
+ dependencies = self.send(symbol) # e.g. build.tags_for_that_this_build_is_last
7
+
8
+ dependencies.map do |entry|
9
+ foreign_key = self.class.reflect_on_association(symbol).foreign_key.to_sym
10
+ entry.update(foreign_key => nil) # e.g. tag.update(last_build_id: nil)
11
+ {
12
+ related_table: entry.class.table_name,
13
+ foreign_key: foreign_key,
14
+ parent_id: self.id,
15
+ related_id: entry.id
16
+ }
17
+ end
18
+ end.flatten
19
+ end
20
+
21
+ def nullify_all_dependencies
22
+ nullify_dependencies(symbols_of_all_direct_dependencies)
23
+ end
24
+
25
+ def nullify_default_dependencies
26
+ nullify_dependencies(default_dependencies_symbols_to_nullify)
27
+ end
28
+
29
+ def default_dependencies_symbols_to_nullify
30
+ self.class.default_dependencies_symbols_to_nullify
31
+ end
32
+
33
+ def self.default_dependencies_symbols_to_nullify
34
+ raise "self.default_dependencies_symbols_to_nullify not implemented in the #{self.class} class"
35
+ end
36
+
37
+ def default_dependencies_to_nullify
38
+ default_dependencies_symbols_to_nullify.map do |symbol|
39
+ self.send(symbol).to_a
40
+ end.flatten(1)
41
+ end
42
+ end
data/lib/travis-backup.rb CHANGED
@@ -5,19 +5,41 @@ require 'active_support/time'
5
5
  require 'config'
6
6
  require 'db_helper'
7
7
  require 'dry_run_reporter'
8
+ require 'models/abuse'
9
+ require 'models/annotation'
8
10
  require 'models/repository'
9
- require 'models/log'
10
11
  require 'models/branch'
11
- require 'models/tag'
12
+ require 'models/broadcast'
13
+ require 'models/build'
12
14
  require 'models/commit'
13
15
  require 'models/cron'
16
+ require 'models/email'
17
+ require 'models/invoice'
18
+ require 'models/job'
19
+ require 'models/log'
20
+ require 'models/membership'
21
+ require 'models/message'
22
+ require 'models/organization'
23
+ require 'models/owner_group'
24
+ require 'models/permission'
14
25
  require 'models/pull_request'
15
- require 'models/ssl_key'
26
+ require 'models/queueable_job'
27
+ require 'models/repository'
16
28
  require 'models/request'
29
+ require 'models/ssl_key'
17
30
  require 'models/stage'
31
+ require 'models/star'
32
+ require 'models/subscription'
33
+ require 'models/tag'
34
+ require 'models/token'
35
+ require 'models/trial_allowance'
36
+ require 'models/trial'
37
+ require 'models/user_beta_feature'
38
+ require 'models/user'
18
39
  require 'backup/move_logs'
19
40
  require 'backup/remove_orphans'
20
- require 'backup/remove_old'
41
+ require 'backup/load_from_files'
42
+ require 'backup/remove_specified'
21
43
 
22
44
  # main travis-backup class
23
45
  class Backup
@@ -39,10 +61,12 @@ class Backup
39
61
  def run(args={})
40
62
  if @config.move_logs
41
63
  Backup::MoveLogs.new(@config, @db_helper, @dry_run_reporter).run
64
+ elsif @config.load_from_files
65
+ Backup::LoadFromFiles.new(@config, @dry_run_reporter).run
42
66
  elsif @config.remove_orphans
43
67
  Backup::RemoveOrphans.new(@config, @dry_run_reporter).run
44
68
  else
45
- Backup::RemoveOld.new(@config, @dry_run_reporter).run(args)
69
+ Backup::RemoveSpecified.new(@config, @dry_run_reporter).run(args)
46
70
  end
47
71
 
48
72
  @dry_run_reporter.print_report if @config.dry_run
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'travis-backup'
3
- s.version = '0.2.1'
3
+ s.version = '0.3.0'
4
4
  s.summary = 'Travis CI backup tool'
5
5
  s.authors = ['Karol Selak']
6
6
  s.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: travis-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Selak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-04 00:00:00.000000000 Z
11
+ date: 2021-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -210,13 +210,13 @@ description:
210
210
  email:
211
211
  executables:
212
212
  - setup
213
- - rails
213
+ - console
214
+ - rake
215
+ - travis_backup
214
216
  - spring
215
- - yarn
217
+ - rails
216
218
  - bundle
217
- - travis_backup
218
- - rake
219
- - console
219
+ - yarn
220
220
  extensions: []
221
221
  extra_rdoc_files: []
222
222
  files:
@@ -260,27 +260,53 @@ files:
260
260
  - config/spring.rb
261
261
  - db/schema.sql
262
262
  - dump/.keep
263
+ - lib/backup/load_from_files.rb
263
264
  - lib/backup/move_logs.rb
264
- - lib/backup/remove_old.rb
265
265
  - lib/backup/remove_orphans.rb
266
+ - lib/backup/remove_specified.rb
267
+ - lib/backup/remove_specified/remove_heavy_data.rb
268
+ - lib/backup/remove_specified/remove_with_all_dependencies.rb
269
+ - lib/backup/remove_specified/shared.rb
270
+ - lib/backup/save_file.rb
271
+ - lib/backup/save_id_hash_to_file.rb
272
+ - lib/backup/save_nullified_rels_to_file.rb
266
273
  - lib/config.rb
267
274
  - lib/db_helper.rb
268
275
  - lib/dry_run_reporter.rb
276
+ - lib/id_hash.rb
277
+ - lib/ids_of_all_dependencies.rb
278
+ - lib/model.rb
279
+ - lib/models/abuse.rb
280
+ - lib/models/annotation.rb
269
281
  - lib/models/branch.rb
282
+ - lib/models/broadcast.rb
270
283
  - lib/models/build.rb
271
284
  - lib/models/commit.rb
272
285
  - lib/models/cron.rb
286
+ - lib/models/email.rb
287
+ - lib/models/invoice.rb
273
288
  - lib/models/job.rb
274
289
  - lib/models/log.rb
275
- - lib/models/model.rb
290
+ - lib/models/membership.rb
291
+ - lib/models/message.rb
276
292
  - lib/models/organization.rb
293
+ - lib/models/owner_group.rb
294
+ - lib/models/permission.rb
277
295
  - lib/models/pull_request.rb
296
+ - lib/models/queueable_job.rb
278
297
  - lib/models/repository.rb
279
298
  - lib/models/request.rb
280
299
  - lib/models/ssl_key.rb
281
300
  - lib/models/stage.rb
301
+ - lib/models/star.rb
302
+ - lib/models/subscription.rb
282
303
  - lib/models/tag.rb
304
+ - lib/models/token.rb
305
+ - lib/models/trial.rb
306
+ - lib/models/trial_allowance.rb
283
307
  - lib/models/user.rb
308
+ - lib/models/user_beta_feature.rb
309
+ - lib/nullify_dependencies.rb
284
310
  - lib/travis-backup.rb
285
311
  - log/.keep
286
312
  - package.json
@@ -1,204 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Backup
4
- class RemoveOld
5
- attr_reader :config
6
-
7
- def initialize(config, dry_run_reporter=nil)
8
- @config = config
9
- @dry_run_reporter = dry_run_reporter
10
- end
11
-
12
- def dry_run_report
13
- @dry_run_reporter.report
14
- end
15
-
16
- def run(args={})
17
- user_id = args[:user_id] || @config.user_id
18
- repo_id = args[:repo_id] || @config.repo_id
19
- org_id = args[:org_id] || @config.org_id
20
-
21
- if user_id
22
- process_repos_for_owner(user_id, 'User')
23
- elsif org_id
24
- process_repos_for_owner(org_id, 'Organization')
25
- elsif repo_id
26
- process_repo_with_id(repo_id)
27
- else
28
- process_all_repos
29
- end
30
- end
31
-
32
- def process_repos_for_owner(owner_id, owner_type)
33
- Repository.where('owner_id = ? and owner_type = ?', owner_id, owner_type).order(:id).each do |repository|
34
- process_repo(repository)
35
- end
36
- end
37
-
38
- def process_repo_with_id(repo_id)
39
- process_repo(Repository.find(repo_id))
40
- end
41
-
42
- def process_all_repos
43
- Repository.order(:id).each do |repository|
44
- process_repo(repository)
45
- end
46
- end
47
-
48
- def process_repo(repository)
49
- process_repo_builds(repository)
50
- process_repo_requests(repository)
51
- end
52
-
53
- def process_repo_builds(repository) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
54
- threshold = @config.threshold.to_i.months.ago.to_datetime
55
- current_build_id = repository.current_build_id || -1
56
- repository.builds.where('created_at < ? and id != ?', threshold, current_build_id)
57
- .in_batches(of: @config.limit.to_i).map do |builds_batch|
58
- if @config.if_backup
59
- file_prefix = "repository_#{repository.id}"
60
- save_and_destroy_builds_batch(builds_batch, file_prefix)
61
- else
62
- destroy_builds_batch(builds_batch)
63
- end
64
- end.compact.reduce(&:&)
65
- end
66
-
67
- def process_repo_requests(repository)
68
- threshold = @config.threshold.to_i.months.ago.to_datetime
69
- repository.requests.where('created_at < ?', threshold)
70
- .in_batches(of: @config.limit.to_i).map do |requests_batch|
71
- @config.if_backup ? save_and_destroy_requests_batch(requests_batch, repository) : destroy_requests_batch(requests_batch)
72
- end.compact
73
- end
74
-
75
- private
76
-
77
- def save_and_destroy_builds_batch(builds_batch, file_prefix)
78
- builds_export = builds_batch.map(&:attributes)
79
-
80
- dependencies_saved = builds_batch.map do |build|
81
- save_build_jobs_and_logs(build, file_prefix)
82
- end.reduce(&:&)
83
-
84
- if dependencies_saved
85
- file_name = "#{file_prefix}_builds_#{builds_batch.first.id}-#{builds_batch.last.id}.json"
86
- pretty_json = JSON.pretty_generate(builds_export)
87
- save_file(file_name, pretty_json) ? destroy_builds_batch(builds_batch) : false
88
- else
89
- false
90
- end
91
- end
92
-
93
- def save_build_jobs_and_logs(build, file_prefix)
94
- build.jobs.in_batches(of: @config.limit.to_i).map do |jobs_batch|
95
- file_prefix = "#{file_prefix}_build_#{build.id}"
96
- save_jobs_batch(jobs_batch, file_prefix)
97
- end.compact.reduce(&:&)
98
- end
99
-
100
- def save_jobs_batch(jobs_batch, file_prefix)
101
- jobs_export = jobs_batch.map(&:attributes)
102
-
103
- logs_saved = jobs_batch.map do |job|
104
- save_job_logs(job, file_prefix)
105
- end.reduce(&:&)
106
-
107
- if logs_saved
108
- file_name = "#{file_prefix}_jobs_#{jobs_batch.first.id}-#{jobs_batch.last.id}.json"
109
- pretty_json = JSON.pretty_generate(jobs_export)
110
- save_file(file_name, pretty_json)
111
- else
112
- false
113
- end
114
- end
115
-
116
- def save_job_logs(job, file_prefix)
117
- job.logs.in_batches(of: @config.limit.to_i).map do |logs_batch|
118
- file_prefix = "#{file_prefix}_job_#{job.id}"
119
- save_logs_batch(logs_batch, file_prefix)
120
- end.compact.reduce(&:&)
121
- end
122
-
123
- def save_logs_batch(logs_batch, file_prefix)
124
- logs_export = logs_batch.map(&:attributes)
125
- file_name = "#{file_prefix}_logs_#{logs_batch.first.id}-#{logs_batch.last.id}.json"
126
- pretty_json = JSON.pretty_generate(logs_export)
127
- save_file(file_name, pretty_json)
128
- end
129
-
130
- def destroy_builds_batch(builds_batch)
131
- return destroy_builds_batch_dry(builds_batch) if @config.dry_run
132
-
133
- builds_batch.each(&:destroy)
134
- end
135
-
136
- def destroy_builds_batch_dry(builds_batch)
137
- @dry_run_reporter.add_to_report(:builds, *builds_batch.map(&:id))
138
-
139
- jobs_ids = builds_batch.map do |build|
140
- build.jobs.map(&:id) || []
141
- end.flatten
142
-
143
- @dry_run_reporter.add_to_report(:jobs, *jobs_ids)
144
-
145
- logs_ids = builds_batch.map do |build|
146
- build.jobs.map do |job|
147
- job.logs.map(&:id) || []
148
- end.flatten || []
149
- end.flatten
150
-
151
- @dry_run_reporter.add_to_report(:logs, *logs_ids)
152
- end
153
-
154
- def save_and_destroy_requests_batch(requests_batch, repository)
155
- requests_export = export_requests(requests_batch)
156
- file_name = "repository_#{repository.id}_requests_#{requests_batch.first.id}-#{requests_batch.last.id}.json"
157
- pretty_json = JSON.pretty_generate(requests_export)
158
- if save_file(file_name, pretty_json)
159
- destroy_requests_batch(requests_batch)
160
- end
161
- requests_export
162
- end
163
-
164
- def destroy_requests_batch(requests_batch)
165
- return destroy_requests_batch_dry(requests_batch) if @config.dry_run
166
-
167
- requests_batch.each(&:destroy)
168
- end
169
-
170
- def destroy_requests_batch_dry(requests_batch)
171
- @dry_run_reporter.add_to_report(:requests, *requests_batch.map(&:id))
172
- end
173
-
174
- def save_file(file_name, content) # rubocop:disable Metrics/MethodLength
175
- return true if @config.dry_run
176
-
177
- saved = false
178
- begin
179
- unless File.directory?(@config.files_location)
180
- FileUtils.mkdir_p(@config.files_location)
181
- end
182
-
183
- File.open(file_path(file_name), 'w') do |file|
184
- file.write(content)
185
- file.close
186
- saved = true
187
- end
188
- rescue => e
189
- print "Failed to save #{file_name}, error: #{e.inspect}\n"
190
- end
191
- saved
192
- end
193
-
194
- def file_path(file_name)
195
- "#{@config.files_location}/#{file_name}"
196
- end
197
-
198
- def export_requests(requests)
199
- requests.map do |request|
200
- request.attributes
201
- end
202
- end
203
- end
204
- end
data/lib/models/model.rb DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record'
4
-
5
- # Model class
6
- class Model < ActiveRecord::Base
7
- self.abstract_class = true
8
- end