kuroko2-updater 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cd5411880d8d46b6f01127b10f15c1b7949e4eb4f024d5481cab786c03912d66
4
+ data.tar.gz: 1689cfe567e18c01524d5b13096a36f26b702d83a1c7cd62b1ac843ab5c046b3
5
+ SHA512:
6
+ metadata.gz: dc67e62689aad9f7c2f6f5d35eca57cb02040967dce1c6e730a6bed5b82db3c123a2cb7d1794024e7b092ffd806744aca8f6e29eaf2e0f772347f4a2a98c3a25
7
+ data.tar.gz: 4f4508b81ed8637dea3dfc6e37e9662f31840fb3d86fd0a6de2d6a7fa0212664b009b622c5414bfcadf9e0536741d0412b2586e45856abce73cfa36e2ff222c5
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+
13
+ # Rubocop remote configs
14
+ .rubocop-*
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,2 @@
1
+ inherit_from:
2
+ - https://raw.githubusercontent.com/cookpad/global-style-guides/master/.rubocop.yml
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.1
7
+ before_install: gem install bundler -v 2.0.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in kuroko2-updater.gemspec
4
+ gemspec
@@ -0,0 +1,88 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ kuroko2-updater (0.1.2)
5
+ activesupport
6
+ faraday (>= 0.15)
7
+ faraday_middleware (>= 0.13)
8
+ whenever (~> 0.11)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activesupport (6.0.2.2)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ zeitwerk (~> 2.2)
19
+ ast (2.4.0)
20
+ chronic (0.10.2)
21
+ concurrent-ruby (1.1.6)
22
+ diff-lcs (1.3)
23
+ faraday (1.0.1)
24
+ multipart-post (>= 1.2, < 3)
25
+ faraday_middleware (1.0.0)
26
+ faraday (~> 1.0)
27
+ i18n (1.8.2)
28
+ concurrent-ruby (~> 1.0)
29
+ jaro_winkler (1.5.4)
30
+ minitest (5.14.0)
31
+ multipart-post (2.1.1)
32
+ parallel (1.19.1)
33
+ parser (2.7.1.2)
34
+ ast (~> 2.4.0)
35
+ rack (2.2.2)
36
+ rainbow (3.0.0)
37
+ rake (13.0.1)
38
+ rexml (3.2.4)
39
+ rspec (3.9.0)
40
+ rspec-core (~> 3.9.0)
41
+ rspec-expectations (~> 3.9.0)
42
+ rspec-mocks (~> 3.9.0)
43
+ rspec-core (3.9.1)
44
+ rspec-support (~> 3.9.1)
45
+ rspec-expectations (3.9.1)
46
+ diff-lcs (>= 1.2.0, < 2.0)
47
+ rspec-support (~> 3.9.0)
48
+ rspec-mocks (3.9.1)
49
+ diff-lcs (>= 1.2.0, < 2.0)
50
+ rspec-support (~> 3.9.0)
51
+ rspec-support (3.9.2)
52
+ rubocop (0.82.0)
53
+ jaro_winkler (~> 1.5.1)
54
+ parallel (~> 1.10)
55
+ parser (>= 2.7.0.1)
56
+ rainbow (>= 2.2.2, < 4.0)
57
+ rexml
58
+ ruby-progressbar (~> 1.7)
59
+ unicode-display_width (>= 1.4.0, < 2.0)
60
+ rubocop-performance (1.5.2)
61
+ rubocop (>= 0.71.0)
62
+ rubocop-rails (2.5.2)
63
+ activesupport
64
+ rack (>= 1.1)
65
+ rubocop (>= 0.72.0)
66
+ ruby-progressbar (1.10.1)
67
+ thread_safe (0.3.6)
68
+ tzinfo (1.2.7)
69
+ thread_safe (~> 0.1)
70
+ unicode-display_width (1.7.0)
71
+ whenever (0.11.0)
72
+ chronic (>= 0.6.3)
73
+ zeitwerk (2.3.0)
74
+
75
+ PLATFORMS
76
+ ruby
77
+
78
+ DEPENDENCIES
79
+ bundler (~> 2.0)
80
+ kuroko2-updater!
81
+ rake (~> 13.0)
82
+ rspec (~> 3.0)
83
+ rubocop (~> 0.71)
84
+ rubocop-performance
85
+ rubocop-rails
86
+
87
+ BUNDLED WITH
88
+ 2.1.4
@@ -0,0 +1,88 @@
1
+ # Kuroko2 Updater
2
+
3
+ ## Background
4
+
5
+ A tool that uses a [whenever](https://github.com/javan/whenever) style config
6
+ file to configure [kuroko2](https://github.com/cookpad/kuroko2)
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'kuroko2-updater'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ ## Status
21
+
22
+ Experimental, not intended for general use, no plans for ongoing maintenance.
23
+
24
+ ## Usage
25
+
26
+ Some modifications must be made to the schedule.rb file to support using
27
+ kuroko2, rather than cron, here is an example of the additions required:
28
+
29
+
30
+ ```ruby
31
+ set :job_template, <<~TEMPLATE
32
+ queue: hako-executor
33
+ docker_application: hello-world-batch
34
+ env: :environment_variable=:environment
35
+ hako_oneshot: :job
36
+ TEMPLATE
37
+
38
+ job_type :rake, "bundle exec rake :task"
39
+
40
+ # These tags scope the job definitions that will be managed with this config.
41
+ set :kuroko2_tags, %w(hello-world production scheduled)
42
+
43
+ # These are kuroku2 user ids for the Admin user(s) of the jobs managed
44
+ # by this tool. See the /users page to find the id of the
45
+ # user(s) you want to have this responsibility.
46
+ set :kuroko2_users, [1]
47
+
48
+ # This description is added to each job definition created in kuroko2 to
49
+ # warn people not to manually edit the jobs managed by this file!
50
+ set :kuroko2_job_description, <<~DESC
51
+ This job is managed by an automation tool.
52
+
53
+ **Warning DO NOT EDIT**
54
+
55
+ Please do not edit this job definition directly
56
+ but instead make a pull request to https://github.com/cookpad/hello-world/blob/master/config/schedule.rb
57
+ DESC
58
+
59
+ set :kuroko2_slack_channel, "#hello-world-alerts"
60
+ ```
61
+
62
+ As part of the deployment process run the `kuroko2-updater` command.
63
+
64
+ By default this reads `config/schedule.rb` but another file can be passed as an argument.
65
+
66
+ ## Config
67
+
68
+ This config is **required** and must be included in the environment for this
69
+ tool to run without error!
70
+
71
+ | Var | notes | e.g |
72
+ |-----|-------|-----|
73
+ | `KUROKO2_API_URL` | The URL of the kuroko2 API | `https://kuroko2.example.com/v1` |
74
+ | `KUROKO2_API_USER` | The username for kuroku2 API auth | `hello-world` |
75
+ | `KUROKO2_API_KEY` | The password/key for kuroku2 API auth | `secret-password` |
76
+
77
+ ## Warning
78
+
79
+ This gem is currently only intended to be used internally at Cookpad. And we cannot
80
+ really recommend it's use as we created it to ease some migration issues in a
81
+ specific project.
82
+
83
+ This tool heavily monkey patches and exposes some internal details of whenever
84
+ in a way that I am sure is not supported by the author of that tool, so it
85
+ may well break unexpectedly if you update whenever!
86
+
87
+ We intend to improve this tool, or create other tooling to enable this workflow
88
+ more generically, at some point in the future.
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "rubocop/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new
7
+
8
+ task default: %i(spec rubocop)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "kuroko2/updater"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "kuroko2/updater"
4
+
5
+ schedule_config = ARGV[0] || "config/schedule.rb"
6
+
7
+ Kuroko2::Updater.new(
8
+ job_list: Whenever::JobList.new(file: schedule_config)
9
+ ).run
@@ -0,0 +1,32 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "kuroko2/updater/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "kuroko2-updater"
7
+ spec.version = Kuroko2::Updater::VERSION
8
+ spec.authors = ["Ed Robinson"]
9
+ spec.email = ["edward-robinson@cookpad.com"]
10
+ spec.summary = "A tool to manage kuroko2 job-definitions based on a schedule.rb file"
11
+
12
+ # Specify which files should be added to the gem when it is released.
13
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
14
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
15
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ end
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport"
22
+ spec.add_dependency "faraday", ">= 0.15"
23
+ spec.add_dependency "faraday_middleware", ">= 0.13"
24
+ spec.add_dependency "whenever", "~> 0.11"
25
+
26
+ spec.add_development_dependency "bundler", "~> 2.0"
27
+ spec.add_development_dependency "rake", "~> 13.0"
28
+ spec.add_development_dependency "rspec", "~> 3.0"
29
+ spec.add_development_dependency "rubocop", "~> 0.71"
30
+ spec.add_development_dependency "rubocop-performance"
31
+ spec.add_development_dependency "rubocop-rails"
32
+ end
@@ -0,0 +1,137 @@
1
+ require "kuroko2/updater/version"
2
+ require "kuroko2/updater/whenever"
3
+ require "kuroko2/updater/client/definition"
4
+ require "logger"
5
+
6
+ module Kuroko2
7
+ class Updater
8
+ class ValidationError < RuntimeError; end
9
+
10
+ def initialize(job_list:, client: Kuroko2::Updater::Client::Definition.new)
11
+ @client = client
12
+ @job_list = job_list
13
+ end
14
+
15
+ def run
16
+ validate_job_list
17
+
18
+ to_delete.each { |job| client.delete(job) }
19
+ to_create.each { |job| client.create(job) }
20
+ to_update.each { |job| client.update(job) }
21
+ end
22
+
23
+ private
24
+
25
+ def validate_job_list
26
+ fail ValidationError, ":kuroko2_tags was not set set in the config file" unless tags.any?
27
+ fail ValidationError, ":kuroko2_users was not set in the config file" unless users.any?
28
+ fail ValidationError, "#{duplicated_jobs.join(',')} was specified more than once" if duplicated_jobs.any?
29
+ end
30
+
31
+ def duplicated_jobs
32
+ names = desired_jobs.map { |job| job[:name] }
33
+ names.select { |name| names.count(name) > 1 }.uniq
34
+ end
35
+
36
+ def to_delete
37
+ existing_jobs.reject do |existing_job|
38
+ desired_jobs.any? do |desired_job|
39
+ desired_job[:name] == existing_job[:name]
40
+ end
41
+ end
42
+ end
43
+
44
+ def to_create
45
+ desired_jobs.reject do |desired_job|
46
+ existing_jobs.any? do |existing_job|
47
+ desired_job[:name] == existing_job[:name]
48
+ end
49
+ end
50
+ end
51
+
52
+ def to_update
53
+ (desired_jobs - to_create).map do |job|
54
+ job[:id] = id_for(job)
55
+ job
56
+ end
57
+ end
58
+
59
+ def id_for(job)
60
+ existing_jobs.find { |existing_job| existing_job[:name] == job[:name] }[:id]
61
+ end
62
+
63
+ def existing_jobs
64
+ @_existing_jobs ||= client.list(tags)
65
+ end
66
+
67
+ def desired_jobs
68
+ @_desired_jobs ||= job_list.time_and_jobs.flat_map do |time, jobs|
69
+ jobs.map do |job|
70
+ {
71
+ name: job.task,
72
+ script: job.output,
73
+ description: job_description,
74
+ cron: cron(time, job),
75
+ slack_channel: slack_channel,
76
+ user_id: users,
77
+ tags: tags,
78
+ hipchat_notify_finished: notify_finished,
79
+ notify_cancellation: notify_cancellation
80
+ }
81
+ end
82
+ end
83
+ end
84
+
85
+ def slack_channel
86
+ job_list.kuroko2_slack_channel
87
+ rescue NoMethodError
88
+ nil
89
+ end
90
+
91
+ def job_description
92
+ job_list.kuroko2_job_description
93
+ rescue NoMethodError
94
+ <<~DESC
95
+ This job is managed by an automation tool.
96
+
97
+ **Warning DO NOT EDIT**
98
+
99
+ Please do not edit this job definition directly.
100
+ DESC
101
+ end
102
+
103
+ def notify_finished
104
+ job_list.kuroko2_notify_finished
105
+ rescue NoMethodError
106
+ false
107
+ end
108
+
109
+ def notify_cancellation
110
+ job_list.kuroko2_notify_cancellation
111
+ rescue NoMethodError
112
+ true
113
+ end
114
+
115
+ def tags
116
+ job_list.kuroko2_tags
117
+ rescue NoMethodError
118
+ []
119
+ end
120
+
121
+ def users
122
+ job_list.kuroko2_users
123
+ rescue NoMethodError
124
+ []
125
+ end
126
+
127
+ def cron(times, job)
128
+ ::Whenever::Output::Cron.enumerate(times).flat_map do |time|
129
+ ::Whenever::Output::Cron.enumerate(job.at).map do |at|
130
+ ::Whenever::Output::Cron.new(time, nil, at).time_in_cron_syntax
131
+ end
132
+ end
133
+ end
134
+
135
+ attr_reader :job_list, :client
136
+ end
137
+ end
@@ -0,0 +1,70 @@
1
+ require "faraday"
2
+ require "faraday_middleware"
3
+ require "active_support/core_ext/hash"
4
+
5
+ module Kuroko2
6
+ class Updater
7
+ class Client
8
+ class Error < RuntimeError; end
9
+ class Definition
10
+ PATH = "definitions".freeze
11
+
12
+ def list(tags = nil)
13
+ response = client.get(PATH) do |req|
14
+ req.params[:tags] = tags if tags
15
+ end
16
+ handle_errors(response)
17
+ response.body.map(&:deep_symbolize_keys)
18
+ end
19
+
20
+ def create(params)
21
+ log.info "creating: #{params[:name]}"
22
+ response = client.post(PATH) do |req|
23
+ req.body = params
24
+ end
25
+ handle_errors(response)
26
+ response.body.deep_symbolize_keys
27
+ end
28
+
29
+ def update(params)
30
+ params = params.dup
31
+ id = params.delete(:id)
32
+ log.info "updating: #{id} #{params[:name]}"
33
+ response = client.put("#{PATH}/#{id}") do |req|
34
+ req.body = params
35
+ end
36
+ handle_errors(response)
37
+ true
38
+ end
39
+
40
+ def delete(params)
41
+ params = params.dup
42
+ id = params.delete(:id)
43
+ log.info "deleting: #{id} #{params[:name]}"
44
+ response = client.delete("#{PATH}/#{id}")
45
+ handle_errors(response)
46
+ true
47
+ end
48
+
49
+ private
50
+
51
+ def handle_errors(response)
52
+ fail Kuroko2::Updater::Client::Error, response.body["message"] unless response.success?
53
+ end
54
+
55
+ def log
56
+ Logger.new(STDERR)
57
+ end
58
+
59
+ def client
60
+ @_client ||= Faraday.new(url: ENV.fetch("KUROKO2_API_URL")) do |config|
61
+ config.basic_auth(ENV.fetch("KUROKO2_API_USER"), ENV.fetch("KUROKO2_API_KEY"))
62
+ config.use FaradayMiddleware::EncodeJson
63
+ config.use FaradayMiddleware::ParseJson
64
+ config.adapter Faraday.default_adapter
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,5 @@
1
+ module Kuroko2
2
+ class Updater
3
+ VERSION = "0.1.2".freeze
4
+ end
5
+ end
@@ -0,0 +1,37 @@
1
+ require "whenever"
2
+
3
+ module Kuroko2
4
+ class Updater
5
+ module Whenever
6
+ class ::Whenever::Job
7
+ def task
8
+ @options[:task]
9
+ end
10
+
11
+ protected
12
+
13
+ # patch whenever not to chomp newlines, as kuroko2 scripts need them
14
+ def process_template(template, options)
15
+ template.gsub(/:\w+/) do |key|
16
+ before_and_after = [$`[-1..-1], $'[0..0]]
17
+ option = options[key.sub(":", "").to_sym] || key
18
+
19
+ if before_and_after.all? { |c| c == "'" }
20
+ escape_single_quotes(option)
21
+ elsif before_and_after.all? { |c| c == '"' }
22
+ escape_double_quotes(option)
23
+ else
24
+ option
25
+ end
26
+ end.strip
27
+ end
28
+ end
29
+
30
+ class ::Whenever::JobList
31
+ def time_and_jobs
32
+ @jobs.values.reduce({}, :merge)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,199 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kuroko2-updater
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Ed Robinson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-05-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
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: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0.15'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0.15'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday_middleware
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0.13'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0.13'
55
+ - !ruby/object:Gem::Dependency
56
+ name: whenever
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.11'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.11'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '13.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '13.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.71'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.71'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-performance
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: rubocop-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
+ description:
154
+ email:
155
+ - edward-robinson@cookpad.com
156
+ executables:
157
+ - kuroko2-updater
158
+ extensions: []
159
+ extra_rdoc_files: []
160
+ files:
161
+ - ".gitignore"
162
+ - ".rspec"
163
+ - ".rubocop.yml"
164
+ - ".travis.yml"
165
+ - Gemfile
166
+ - Gemfile.lock
167
+ - README.md
168
+ - Rakefile
169
+ - bin/console
170
+ - bin/setup
171
+ - exe/kuroko2-updater
172
+ - kuroko2-updater.gemspec
173
+ - lib/kuroko2/updater.rb
174
+ - lib/kuroko2/updater/client/definition.rb
175
+ - lib/kuroko2/updater/version.rb
176
+ - lib/kuroko2/updater/whenever.rb
177
+ homepage:
178
+ licenses: []
179
+ metadata: {}
180
+ post_install_message:
181
+ rdoc_options: []
182
+ require_paths:
183
+ - lib
184
+ required_ruby_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ required_rubygems_version: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ requirements: []
195
+ rubygems_version: 3.0.3
196
+ signing_key:
197
+ specification_version: 4
198
+ summary: A tool to manage kuroko2 job-definitions based on a schedule.rb file
199
+ test_files: []