travis-backup 0.0.1

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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +33 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +212 -0
  6. data/README.md +109 -0
  7. data/Rakefile +18 -0
  8. data/bin/bundle +114 -0
  9. data/bin/console +8 -0
  10. data/bin/rails +5 -0
  11. data/bin/rake +7 -0
  12. data/bin/setup +36 -0
  13. data/bin/spring +14 -0
  14. data/bin/travis_backup +7 -0
  15. data/bin/yarn +17 -0
  16. data/config/application.rb +22 -0
  17. data/config/boot.rb +4 -0
  18. data/config/cable.yml +10 -0
  19. data/config/credentials.yml.enc +1 -0
  20. data/config/database.yml +20 -0
  21. data/config/environment.rb +5 -0
  22. data/config/environments/development.rb +76 -0
  23. data/config/environments/production.rb +120 -0
  24. data/config/environments/test.rb +60 -0
  25. data/config/initializers/application_controller_renderer.rb +8 -0
  26. data/config/initializers/assets.rb +14 -0
  27. data/config/initializers/backtrace_silencers.rb +8 -0
  28. data/config/initializers/content_security_policy.rb +30 -0
  29. data/config/initializers/cookies_serializer.rb +5 -0
  30. data/config/initializers/filter_parameter_logging.rb +6 -0
  31. data/config/initializers/inflections.rb +16 -0
  32. data/config/initializers/mime_types.rb +4 -0
  33. data/config/initializers/permissions_policy.rb +11 -0
  34. data/config/initializers/wrap_parameters.rb +14 -0
  35. data/config/locales/en.yml +33 -0
  36. data/config/puma.rb +43 -0
  37. data/config/routes.rb +3 -0
  38. data/config/settings.yml +7 -0
  39. data/config/spring.rb +6 -0
  40. data/config.ru +5 -0
  41. data/db/schema.sql +3502 -0
  42. data/dump/.keep +0 -0
  43. data/lib/config.rb +127 -0
  44. data/lib/models/build.rb +13 -0
  45. data/lib/models/job.rb +13 -0
  46. data/lib/models/model.rb +8 -0
  47. data/lib/models/organization.rb +7 -0
  48. data/lib/models/repository.rb +11 -0
  49. data/lib/models/user.rb +7 -0
  50. data/lib/travis-backup.rb +134 -0
  51. data/log/.keep +0 -0
  52. data/package.json +11 -0
  53. data/tmp/.keep +0 -0
  54. data/travis-backup.gemspec +29 -0
  55. data/vendor/.keep +0 -0
  56. metadata +286 -0
data/dump/.keep ADDED
File without changes
data/lib/config.rb ADDED
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+ require 'optparse'
3
+
4
+ class Config
5
+ attr_reader :if_backup, :dry_run, :limit, :threshold, :files_location, :database_url, :user_id, :repo_id, :org_id
6
+
7
+ def initialize(args={}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
8
+ set_values(args)
9
+ check_values
10
+ end
11
+
12
+ def set_values(args)
13
+ config = yaml_load('config/settings.yml')
14
+ connection_details = yaml_load('config/database.yml')
15
+ argv_opts = argv_options
16
+ @if_backup = first_not_nil(
17
+ args[:if_backup],
18
+ argv_opts[:if_backup],
19
+ ENV['IF_BACKUP'],
20
+ config.dig('backup', 'if_backup'),
21
+ true
22
+ )
23
+ @dry_run = first_not_nil(
24
+ args[:dry_run],
25
+ argv_opts[:dry_run],
26
+ ENV['BACKUP_DRY_RUN'],
27
+ config.dig('backup', 'dry_run'),
28
+ false
29
+ )
30
+ @limit = first_not_nil(
31
+ args[:limit],
32
+ argv_opts[:limit],
33
+ ENV['BACKUP_LIMIT'],
34
+ config.dig('backup', 'limit'),
35
+ 1000
36
+ )
37
+ @threshold = first_not_nil(
38
+ args[:threshold],
39
+ argv_opts[:threshold],
40
+ ENV['BACKUP_THRESHOLD'],
41
+ config.dig('backup', 'threshold')
42
+ )
43
+ @files_location = first_not_nil(
44
+ args[:files_location],
45
+ argv_opts[:files_location],
46
+ ENV['BACKUP_BACKUP_FILES_LOCATION'],
47
+ config.dig('backup', 'files_location'),
48
+ './dump'
49
+ )
50
+ @database_url = first_not_nil(
51
+ args[:database_url],
52
+ argv_opts[:database_url],
53
+ ENV['DATABASE_URL'],
54
+ connection_details.dig(ENV['RAILS_ENV'])
55
+ )
56
+ @user_id = first_not_nil(
57
+ args[:user_id],
58
+ argv_opts[:user_id],
59
+ ENV['USER_ID'],
60
+ config.dig('backup', 'user_id')
61
+ )
62
+ @repo_id = first_not_nil(
63
+ args[:repo_id],
64
+ argv_opts[:repo_id],
65
+ ENV['REPO_ID'],
66
+ config.dig('backup', 'repo_id')
67
+ )
68
+ @org_id = first_not_nil(
69
+ args[:org_id],
70
+ argv_opts[:org_id],
71
+ ENV['ORG_ID'],
72
+ config.dig('backup', 'org_id')
73
+ )
74
+ end
75
+
76
+ def check_values
77
+ if !@threshold
78
+ message = abort_message("Please provide the threshold argument. Data younger than it will be omitted. " +
79
+ "Threshold defines number of months from now.")
80
+ abort message
81
+ end
82
+
83
+ if !@database_url
84
+ message = abort_message("Please provide proper database URL.")
85
+ abort message
86
+ end
87
+ end
88
+
89
+ def abort_message(intro)
90
+ "\n#{intro} Example usage:\n"+
91
+ "\n $ bin/travis_backup 'postgres://my_database_url' --threshold 6\n" +
92
+ "\nYou can also set it using environment variables or config/database.yml file.\n"
93
+ end
94
+
95
+ def argv_options
96
+ argv_copy = ARGV.clone
97
+ options = {}
98
+ OptionParser.new do |opt|
99
+ opt.on('-b', '--backup') { |o| options[:if_backup] = o }
100
+ opt.on('-d', '--dry_run') { |o| options[:dry_run] = o }
101
+ opt.on('-l', '--limit X') { |o| options[:limit] = o.to_i }
102
+ opt.on('-t', '--threshold X') { |o| options[:threshold] = o.to_i }
103
+ opt.on('-f', '--files_location X') { |o| options[:files_location] = o }
104
+ opt.on('-u', '--user_id X') { |o| options[:user_id] = o.to_i }
105
+ opt.on('-r', '--repo_id X') { |o| options[:repo_id] = o.to_i }
106
+ opt.on('-o', '--org_id X') { |o| options[:org_id] = o.to_i }
107
+ end.parse!
108
+
109
+ options[:database_url] = ARGV.shift if ARGV[0]
110
+ argv_copy.each do |arg|
111
+ ARGV.push(arg)
112
+ end
113
+ options
114
+ end
115
+
116
+ def first_not_nil(*arr)
117
+ arr.compact.first
118
+ end
119
+
120
+ def yaml_load(url)
121
+ begin
122
+ YAML.load(File.open(url))
123
+ rescue => e
124
+ {}
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'models/job'
4
+ require 'models/model'
5
+ require 'models/repository'
6
+
7
+ # Build model
8
+ class Build < Model
9
+ belongs_to :repository
10
+ has_many :jobs, -> { order('id') }, foreign_key: :source_id, dependent: :delete_all, class_name: 'Job'
11
+
12
+ self.table_name = 'builds'
13
+ end
data/lib/models/job.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'models/model'
4
+ require 'models/repository'
5
+
6
+ # Job model
7
+ class Job < Model
8
+ self.inheritance_column = :_type_disabled
9
+
10
+ belongs_to :repository
11
+
12
+ self.table_name = 'jobs'
13
+ end
@@ -0,0 +1,8 @@
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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'models/model'
4
+
5
+ class Organization < Model
6
+ self.table_name = 'organizations'
7
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'models/model'
4
+ require 'models/build'
5
+
6
+ # Repository model
7
+ class Repository < Model
8
+ has_many :builds, -> { order('id') }, foreign_key: :repository_id, dependent: :destroy, class_name: 'Build'
9
+
10
+ self.table_name = 'repositories'
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'models/model'
4
+
5
+ class User < Model
6
+ self.table_name = 'users'
7
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/array'
4
+ require 'active_support/time'
5
+ require 'config'
6
+ require 'models/repository'
7
+
8
+ # main travis-backup class
9
+ class Backup
10
+ def initialize(config_args={})
11
+ @config = Config.new(config_args)
12
+
13
+ if @config.dry_run
14
+ @dry_run_removed = {builds: [], jobs: []}
15
+ end
16
+
17
+ connect_db
18
+ end
19
+
20
+ def connect_db
21
+ ActiveRecord::Base.establish_connection(@config.database_url)
22
+ end
23
+
24
+ def run(args={})
25
+ user_id = args[:user_id] || @config.user_id
26
+ repo_id = args[:repo_id] || @config.repo_id
27
+ org_id = args[:org_id] || @config.org_id
28
+
29
+ if user_id
30
+ owner_id = user_id
31
+ owner_type = 'User'
32
+ elsif org_id
33
+ owner_id = org_id
34
+ owner_type = 'Organization'
35
+ elsif repo_id
36
+ repo_id = repo_id
37
+ end
38
+
39
+ if owner_id
40
+ Repository.where('owner_id = ? and owner_type = ?', owner_id, owner_type).order(:id).each do |repository|
41
+ process_repo(repository)
42
+ end
43
+ elsif repo_id
44
+ repository = Repository.find(repo_id)
45
+ process_repo(repository)
46
+ else
47
+ Repository.order(:id).each do |repository|
48
+ process_repo(repository)
49
+ end
50
+ end
51
+
52
+ if @config.dry_run
53
+ puts 'Dry run active. The following data would be removed in normal mode:'
54
+ puts " - builds: #{@dry_run_removed[:builds].to_json}"
55
+ puts " - jobs: #{@dry_run_removed[:jobs].to_json}"
56
+ end
57
+ end
58
+
59
+ def process_repo(repository) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
60
+ threshold = @config.threshold.to_i.months.ago.to_datetime
61
+ current_build_id = repository.current_build_id || -1
62
+ repository.builds.where('created_at < ? and id != ?', threshold, current_build_id)
63
+ .in_groups_of(@config.limit.to_i, false).map do |builds_batch|
64
+ @config.if_backup ? save_and_destroy_batch(builds_batch, repository) : destroy_batch(builds_batch)
65
+ end.compact
66
+ end
67
+
68
+ private
69
+
70
+ def save_and_destroy_batch(builds_batch, repository)
71
+ builds_export = export_builds(builds_batch)
72
+ file_name = "repository_#{repository.id}_builds_#{builds_batch.first.id}-#{builds_batch.last.id}.json"
73
+ pretty_json = JSON.pretty_generate(builds_export)
74
+ if save_file(file_name, pretty_json)
75
+ destroy_batch(builds_batch)
76
+ end
77
+ builds_export
78
+ end
79
+
80
+ def destroy_batch(builds_batch)
81
+ return destroy_batch_dry(builds_batch) if @config.dry_run
82
+
83
+ builds_batch.each(&:destroy)
84
+ end
85
+
86
+ def destroy_batch_dry(builds_batch)
87
+ @dry_run_removed[:builds].concat(builds_batch.map(&:id))
88
+ jobs = builds_batch.map do |build|
89
+ build.jobs.map(&:id) || []
90
+ end.flatten
91
+ @dry_run_removed[:jobs].concat(jobs)
92
+ end
93
+
94
+ def save_file(file_name, content) # rubocop:disable Metrics/MethodLength
95
+ return true if @config.dry_run
96
+
97
+ saved = false
98
+ begin
99
+ unless File.directory?(@config.files_location)
100
+ FileUtils.mkdir_p(@config.files_location)
101
+ end
102
+
103
+ File.open(file_path(file_name), 'w') do |file|
104
+ file.write(content)
105
+ file.close
106
+ saved = true
107
+ end
108
+ rescue => e
109
+ print "Failed to save #{file_name}, error: #{e.inspect}\n"
110
+ end
111
+ saved
112
+ end
113
+
114
+ def file_path(file_name)
115
+ "#{@config.files_location}/#{file_name}"
116
+ end
117
+
118
+ def export_builds(builds)
119
+ builds.map do |build|
120
+ build_export = build.attributes
121
+ build_export[:jobs] = export_jobs(build.jobs)
122
+
123
+ build_export
124
+ end
125
+ end
126
+
127
+ def export_jobs(jobs)
128
+ jobs.map do |job|
129
+ job_export = job.attributes
130
+
131
+ job_export
132
+ end
133
+ end
134
+ end
data/log/.keep ADDED
File without changes
data/package.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "travis-backup",
3
+ "private": true,
4
+ "dependencies": {
5
+ "@rails/ujs": "^6.0.0",
6
+ "turbolinks": "^5.2.0",
7
+ "@rails/activestorage": "^6.0.0",
8
+ "@rails/actioncable": "^6.0.0"
9
+ },
10
+ "version": "0.1.0"
11
+ }
data/tmp/.keep ADDED
File without changes
@@ -0,0 +1,29 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'travis-backup'
3
+ s.version = '0.0.1'
4
+ s.summary = 'Travis CI backup tool'
5
+ s.authors = ['Karol Selak']
6
+ s.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
7
+ s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
8
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
9
+ end
10
+ s.executables = Dir.glob('bin/*').map { |f| File.basename(f) }
11
+ s.require_paths = ["lib"]
12
+ s.license = 'Beerware'
13
+
14
+ s.add_dependency 'activerecord'
15
+ s.add_dependency 'pg'
16
+ s.add_dependency 'pry'
17
+ s.add_dependency 'rails'
18
+
19
+ s.add_dependency 'bootsnap'
20
+ s.add_dependency 'tzinfo-data'
21
+
22
+ s.add_development_dependency 'brakeman'
23
+ s.add_development_dependency 'byebug'
24
+ s.add_development_dependency 'factory_bot'
25
+ s.add_development_dependency 'rspec-rails'
26
+ s.add_development_dependency 'listen'
27
+ s.add_development_dependency 'rubocop', '~> 0.75.1'
28
+ s.add_development_dependency 'rubocop-rspec'
29
+ end
data/vendor/.keep ADDED
File without changes
metadata ADDED
@@ -0,0 +1,286 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: travis-backup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Karol Selak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-08-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pg
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bootsnap
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: tzinfo-data
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: brakeman
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: factory_bot
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rspec-rails
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: listen
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 0.75.1
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 0.75.1
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop-rspec
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ description:
196
+ email:
197
+ executables:
198
+ - setup
199
+ - rails
200
+ - spring
201
+ - yarn
202
+ - bundle
203
+ - travis_backup
204
+ - rake
205
+ - console
206
+ extensions: []
207
+ extra_rdoc_files: []
208
+ files:
209
+ - ".gitignore"
210
+ - ".travis.yml"
211
+ - Gemfile
212
+ - Gemfile.lock
213
+ - README.md
214
+ - Rakefile
215
+ - bin/bundle
216
+ - bin/console
217
+ - bin/rails
218
+ - bin/rake
219
+ - bin/setup
220
+ - bin/spring
221
+ - bin/travis_backup
222
+ - bin/yarn
223
+ - config.ru
224
+ - config/application.rb
225
+ - config/boot.rb
226
+ - config/cable.yml
227
+ - config/credentials.yml.enc
228
+ - config/database.yml
229
+ - config/environment.rb
230
+ - config/environments/development.rb
231
+ - config/environments/production.rb
232
+ - config/environments/test.rb
233
+ - config/initializers/application_controller_renderer.rb
234
+ - config/initializers/assets.rb
235
+ - config/initializers/backtrace_silencers.rb
236
+ - config/initializers/content_security_policy.rb
237
+ - config/initializers/cookies_serializer.rb
238
+ - config/initializers/filter_parameter_logging.rb
239
+ - config/initializers/inflections.rb
240
+ - config/initializers/mime_types.rb
241
+ - config/initializers/permissions_policy.rb
242
+ - config/initializers/wrap_parameters.rb
243
+ - config/locales/en.yml
244
+ - config/puma.rb
245
+ - config/routes.rb
246
+ - config/settings.yml
247
+ - config/spring.rb
248
+ - db/schema.sql
249
+ - dump/.keep
250
+ - lib/config.rb
251
+ - lib/models/build.rb
252
+ - lib/models/job.rb
253
+ - lib/models/model.rb
254
+ - lib/models/organization.rb
255
+ - lib/models/repository.rb
256
+ - lib/models/user.rb
257
+ - lib/travis-backup.rb
258
+ - log/.keep
259
+ - package.json
260
+ - tmp/.keep
261
+ - travis-backup.gemspec
262
+ - vendor/.keep
263
+ homepage:
264
+ licenses:
265
+ - Beerware
266
+ metadata: {}
267
+ post_install_message:
268
+ rdoc_options: []
269
+ require_paths:
270
+ - lib
271
+ required_ruby_version: !ruby/object:Gem::Requirement
272
+ requirements:
273
+ - - ">="
274
+ - !ruby/object:Gem::Version
275
+ version: 2.3.0
276
+ required_rubygems_version: !ruby/object:Gem::Requirement
277
+ requirements:
278
+ - - ">="
279
+ - !ruby/object:Gem::Version
280
+ version: '0'
281
+ requirements: []
282
+ rubygems_version: 3.1.2
283
+ signing_key:
284
+ specification_version: 4
285
+ summary: Travis CI backup tool
286
+ test_files: []