contentful-scheduler-custom 1.4.0 → 1.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f92623b5fe928b9bfe25297cf01e837ab8aa5046
4
- data.tar.gz: f9bf39f91e6d5a3554586eb79f9a586088e29ac8
3
+ metadata.gz: fc1d58e728b500a546433d09f796d8376c3c4f46
4
+ data.tar.gz: 920cdba7ae773d3f19659500683473437a1f9eb6
5
5
  SHA512:
6
- metadata.gz: b879d5aca93a62fe73b284078a404c7a1d6680e71474c1f9b6fb55ec7ed1db82d7bc540282d4084acc3445fce8214ec5efb208bffa9879b1ba42fb6220c4b7b4
7
- data.tar.gz: 5a0467c6f469baafefd4139f46d4188e5a06cb2ecbeb18b83ce29668b920302c2d8f0162f0a730b3a505f3ea312ee17d912b2d9daaa616ef76f5975c2acd1ab1
6
+ metadata.gz: 5be132b5e5c167ef33852f3a118becd6057e597794734f91d1527c8dca7ca3ce2f25bed65290f0e86b6240ed0014f698d42561aeb31bc0d4e67b260f2b8dbf4a
7
+ data.tar.gz: f1a7a8928206d7fbecd1f916f1e2237e01bdda8f8389ea21968c634a14b3ba8829f07a62d016963802dfe67cc9f13e49d8f88a56e3a89f6419e9fe2deacabd87
data/README.md CHANGED
@@ -16,7 +16,8 @@ if the value is a time in the future it will schedule the entry for publishing a
16
16
  A background worker based on the popular `resque` gem will then proceed to actually make the publish call
17
17
  against the Content Management API at the due time. For this the Entries you wish to publish require a
18
18
  customizable Date field, which we advice to call `publishDate`, this field can be configured inside your
19
- `Rakefile` and is specific per-space.
19
+ `Rakefile` and is specific per-space(supports multiple spaces), also please make sure contentBlocks are valid
20
+ as per logic contentBlocks are published first then the page is published, so if there is any contentBlocks missing publishing won't work.
20
21
 
21
22
  You can add multiple spaces to your configuration, making it useful if you have a milti-space setup.
22
23
 
@@ -29,7 +30,7 @@ You can add multiple spaces to your configuration, making it useful if you have
29
30
  Add this line to your application's Gemfile:
30
31
 
31
32
  ```ruby
32
- gem 'contentful-scheduler'
33
+ gem 'contentful-scheduler-custom'
33
34
  ```
34
35
 
35
36
  And then execute:
@@ -38,7 +39,7 @@ And then execute:
38
39
 
39
40
  Or install it yourself as:
40
41
 
41
- $ gem install contentful-scheduler
42
+ $ gem install contentful-scheduler-custom
42
43
 
43
44
  ## Usage
44
45
 
@@ -54,7 +55,7 @@ If you want to roll out your own, you need to follow the next steps:
54
55
  ```ruby
55
56
  source 'https://rubygems.org'
56
57
 
57
- gem 'contentful-scheduler-custom-build-john', '~>1.30'
58
+ gem 'contentful-scheduler-custom', '~>1.4'
58
59
  gem 'contentful-management', '~> 1.0'
59
60
  gem 'resque', '~> 1.0'
60
61
  gem 'resque-scheduler', '~> 4.0'
@@ -87,6 +88,14 @@ config = {
87
88
  password: 'YOUR_REDIS_PASSWORD'
88
89
  },
89
90
  spaces: {
91
+ 'YOUR_SPACE_ID' => {
92
+ publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
93
+ management_token: 'YOUR_TOKEN'
94
+ },
95
+ 'YOUR_SPACE_ID' => {
96
+ publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
97
+ management_token: 'YOUR_TOKEN'
98
+ },
90
99
  'YOUR_SPACE_ID' => {
91
100
  publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
92
101
  management_token: 'YOUR_TOKEN'
@@ -169,6 +178,67 @@ That will allow Heroku to set it's own Port according to their policy.
169
178
 
170
179
  The URL for the webhook then will be on port 80, so you should change it to: `http://YOUR_APPLICATION/scheduler`.
171
180
 
181
+ ## Running in Production Mode
182
+
183
+ After verifying that application is working fine in development mode(run "foreman start" for development mode)
184
+
185
+ Run the following commands
186
+
187
+ 1. sudo foreman export -p5000 --app stp --user username_to_start_from systemd /etc/systemd/system/
188
+
189
+ Output will be like this:
190
+
191
+ [foreman export] cleaning up directory: /etc/systemd/system//graphical.target.wants
192
+ [foreman export] writing: stp-web@.service
193
+ [foreman export] creating: stp-web.target.wants
194
+ [foreman export] symlinking: stp-web.target.wants/stp-web@5000.service -> ../stp-web@.service
195
+ [foreman export] writing: stp-web.target
196
+ [foreman export] writing: stp-celery@.service
197
+ [foreman export] creating: stp-celery.target.wants
198
+ [foreman export] symlinking: stp-celery.target.wants/stp-celery@5100.service -> ../stp-celery@.service
199
+ [foreman export] writing: stp-celery.target
200
+ [foreman export] writing: stp.target
201
+
202
+ 2. cat /etc/systemd/system/stp-web@.service | head -n 10
203
+
204
+ Output will be like this:
205
+
206
+ [Unit]
207
+ PartOf=stp-web.target
208
+
209
+ [Service]
210
+ User=username_to_start_from
211
+ WorkingDirectory=/srv/stp/
212
+ Environment=PORT=%i
213
+ ... HERE OTHER DIRICTIVES FROM YOUR .env file ...
214
+ Environment=DEBUG=0
215
+ ...
216
+
217
+
218
+ 3. Start only gunicorn on port 5700:
219
+
220
+ systemctl start stp-web@5700.service
221
+
222
+ 4. Start whole target:
223
+
224
+ systemctl start stp.target
225
+
226
+ 5. Enable whole target (start on OS boot):
227
+
228
+ systemctl enable stp.target
229
+
230
+ 6. Restarting daemon
231
+
232
+ sudo systemctl daemon-reload
233
+
234
+ sudo systemctl restart stp.target
235
+
236
+ 7. Optional
237
+
238
+ You can also simply define port when call foreman export -pXXXX, but it should be multiple of 1000,
239
+ e.g. 1000, 2000, 3000, 45000 etc.
240
+
241
+
172
242
  ## Contributing
173
243
 
174
244
  Bug reports and pull requests are welcome on GitHub at https://github.com/contentful/contentful-scheduler.rb. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
@@ -0,0 +1,25 @@
1
+ FROM ruby:2.5
2
+ MAINTAINER Bugs Bunny <bbunny@rubyplus.com>
3
+
4
+
5
+
6
+ # Install gems
7
+ ENV APP_HOME /app
8
+ ENV HOME /root
9
+ RUN mkdir $APP_HOME
10
+ RUN chmod -R 777 /app
11
+ RUN chmod -R 777 /root
12
+
13
+
14
+ WORKDIR $APP_HOME
15
+ COPY Gemfile* $APP_HOME/
16
+ RUN bundle install
17
+
18
+ # Upload source
19
+ COPY . $APP_HOME
20
+
21
+ # Start server
22
+ ENV PORT 8080
23
+ EXPOSE 8080
24
+ USER 1001
25
+ CMD ["foreman", "start"]
data/example/Gemfile CHANGED
@@ -1,7 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'contentful-scheduler-custom-build-john', '~>1.30'
3
+ gem 'contentful-scheduler-custom', '~>1.4'
4
4
  gem 'contentful-management', '~> 1.0'
5
5
  gem 'resque', '~> 1.0'
6
- gem 'resque-scheduler', '~> 4.0'
7
- gem 'rake'
6
+ gem 'resque-scheduler', '4.2.1'
7
+ gem 'rake'
8
+ gem 'foreman', '~> 0.84.0'
data/example/Procfile CHANGED
@@ -1,4 +1,4 @@
1
- web: env bundle exec rake contentful:scheduler
1
+ web: PORT=$PORT bundle exec env rake contentful:scheduler
2
2
  monitor: env bundle exec rackup
3
3
  resque: env bundle exec rake resque:work
4
4
  resque_scheduler: env bundle exec rake resque:scheduler
data/example/Rakefile CHANGED
@@ -4,12 +4,12 @@ $stdout.sync = true
4
4
 
5
5
  config = {
6
6
  logger: Logger.new(STDOUT), # Defaults to NullLogger
7
- port: 6378, # Defaults to 8081
7
+ port: 8080, # Defaults to 8081
8
8
  endpoint: '/scheduler', # Defaults to /scheduler
9
9
  redis: {
10
- host: '127.0.0.1',
10
+ host: 'scheduler-redis-db',
11
11
  port: '6379',
12
- password: '5D40001BB59A2EF2439A55DAB7E718609A3A93CC9D3FD414BB13A75933048CD7'
12
+ password: 'password'
13
13
  },
14
14
  spaces: {
15
15
  'qbra4qai2ti2' => {
@@ -42,4 +42,4 @@ namespace :resque do
42
42
  end
43
43
 
44
44
  task :scheduler => :setup_schedule
45
- end
45
+ end
data/example/config.ru CHANGED
@@ -3,9 +3,9 @@ require 'resque/server'
3
3
  require 'resque/scheduler/server'
4
4
 
5
5
  config = {
6
- host: '127.0.0.1',
6
+ host: 'scheduler-redis-db',
7
7
  port: '6379',
8
- password: '5D40001BB59A2EF2439A55DAB7E718609A3A93CC9D3FD414BB13A75933048CD7'
8
+ password: 'password'
9
9
  }
10
10
  Resque.redis = config
11
11
 
@@ -14,30 +14,53 @@ module Contentful
14
14
  end
15
15
 
16
16
  def update_or_create(webhook)
17
- return unless publishable?(webhook)
18
- remove(webhook) if in_queue?(webhook)
19
- return if already_published?(webhook)
17
+ if publishable?(webhook)
18
+ success = update_or_create_for_publish(webhook)
19
+ log_event_success(webhook, success, 'publish', 'added to')
20
+ end
21
+
22
+ if unpublishable?(webhook)
23
+ success = update_or_create_for_unpublish(webhook) && success
24
+ log_event_success(webhook, success, 'unpublish', 'added to')
25
+ end
26
+
27
+ updateContentBlocks(webhook)
28
+ end
29
+
30
+ def update_or_create_for_publish(webhook)
31
+ remove_publish(webhook) if in_publish_queue?(webhook)
32
+ return false unless publish_is_future?(webhook)
20
33
 
21
- success = Resque.enqueue_at(
34
+ return Resque.enqueue_at(
22
35
  publish_date(webhook),
23
36
  ::Contentful::Scheduler::Tasks::Publish,
24
37
  webhook.space_id,
25
38
  webhook.id,
26
39
  ::Contentful::Scheduler.config[:spaces][webhook.space_id][:management_token]
27
40
  )
41
+ end
28
42
 
29
- updateContentBlocks(webhook)
43
+ def update_or_create_for_unpublish(webhook)
44
+ remove_unpublish(webhook) if in_unpublish_queue?(webhook)
45
+ return false unless unpublish_is_future?(webhook)
30
46
 
31
- if success
32
- logger.info "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} successfully added to queue"
33
- else
34
- logger.warn "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} couldn't be added to queue"
35
- end
47
+ return Resque.enqueue_at(
48
+ unpublish_date(webhook),
49
+ ::Contentful::Scheduler::Tasks::Unpublish,
50
+ webhook.space_id,
51
+ webhook.id,
52
+ ::Contentful::Scheduler.config[:spaces][webhook.space_id][:management_token]
53
+ )
36
54
  end
37
55
 
38
56
  def remove(webhook)
57
+ remove_publish(webhook)
58
+ remove_unpublish(webhook)
59
+ end
60
+
61
+ def remove_publish(webhook)
39
62
  return unless publishable?(webhook)
40
- return unless in_queue?(webhook)
63
+ return unless in_publish_queue?(webhook)
41
64
 
42
65
  success = Resque.remove_delayed(
43
66
  ::Contentful::Scheduler::Tasks::Publish,
@@ -48,11 +71,7 @@ module Contentful
48
71
 
49
72
  removeContentBlocks(webhook)
50
73
 
51
- if success
52
- logger.info "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} successfully removed from queue"
53
- else
54
- logger.warn "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} couldn't be removed from queue"
55
- end
74
+ log_event_success(webhook, success, 'publish', 'removed from')
56
75
  end
57
76
 
58
77
  def updateContentBlocks(webhook)
@@ -100,30 +119,70 @@ module Contentful
100
119
  return false unless spaces.key?(webhook.space_id)
101
120
 
102
121
  if webhook_publish_field?(webhook)
103
- return !webhook_publish_field(webhook).nil?
122
+ return !webhook_publish_field(webhook).nil? && publish_is_future?(webhook)
104
123
  end
105
124
 
106
125
  false
107
126
  end
108
127
 
109
- def already_published?(webhook)
110
- return true if publish_date(webhook) < Time.now.utc
111
-
112
- false
128
+ def publish_is_future?(webhook)
129
+ publish_date(webhook) > Time.now.utc
113
130
  end
114
131
 
115
- def in_queue?(webhook)
132
+ def in_publish_queue?(webhook)
116
133
  Resque.peek(::Contentful::Scheduler::Tasks::Publish, 0, -1).any? do |job|
117
134
  job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
118
135
  end
119
136
  end
120
137
 
138
+ def remove_unpublish(webhook)
139
+ return unless unpublishable?(webhook)
140
+ return unless in_unpublish_queue?(webhook)
141
+
142
+ success = Resque.remove_delayed(
143
+ ::Contentful::Scheduler::Tasks::Unpublish,
144
+ webhook.space_id,
145
+ webhook.id,
146
+ ::Contentful::Scheduler.config[:management_token]
147
+ )
148
+
149
+ removeContentBlocks(webhook)
150
+
151
+ log_event_success(webhook, success, 'unpublish', 'removed from')
152
+ end
153
+
154
+ def in_unpublish_queue?(webhook)
155
+ Resque.peek(::Contentful::Scheduler::Tasks::Unpublish, 0, -1).any? do |job|
156
+ job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
157
+ end
158
+ end
159
+
160
+ def unpublish_is_future?(webhook)
161
+ unpublish_date(webhook) > Time.now.utc
162
+ end
163
+
164
+ def unpublishable?(webhook)
165
+ return false unless spaces.key?(webhook.space_id)
166
+
167
+ if webhook_unpublish_field?(webhook)
168
+ return !webhook_unpublish_field(webhook).nil? && unpublish_is_future?(webhook)
169
+ end
170
+
171
+ false
172
+ end
173
+
121
174
  def publish_date(webhook)
122
175
  date_field = webhook_publish_field(webhook)
123
176
  date_field = date_field[date_field.keys[0]] if date_field.is_a? Hash
124
177
  Chronic.parse(date_field).utc
125
178
  end
126
179
 
180
+ def unpublish_date(webhook)
181
+ date_field = webhook_unpublish_field(webhook)
182
+ date_field = date_field[date_field.keys[0]] if date_field.is_a? Hash
183
+ Chronic.parse(date_field).utc
184
+ end
185
+
127
186
  def spaces
128
187
  config[:spaces]
129
188
  end
@@ -132,10 +191,26 @@ module Contentful
132
191
  webhook.fields.key?(spaces.fetch(webhook.space_id, {})[:publish_field])
133
192
  end
134
193
 
194
+ def webhook_unpublish_field?(webhook)
195
+ webhook.fields.key?(spaces.fetch(webhook.space_id, {})[:unpublish_field])
196
+ end
197
+
135
198
  def webhook_publish_field(webhook)
136
199
  webhook.fields[spaces[webhook.space_id][:publish_field]]
137
200
  end
138
201
 
202
+ def webhook_unpublish_field(webhook)
203
+ webhook.fields[spaces[webhook.space_id][:unpublish_field]]
204
+ end
205
+
206
+ def log_event_success(webhook, success, event_kind, action)
207
+ if success
208
+ logger.info "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} successfully #{action} the #{event_kind} queue"
209
+ else
210
+ logger.warn "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} couldn't be #{action} the #{event_kind} queue"
211
+ end
212
+ end
213
+
139
214
  private
140
215
 
141
216
  def initialize(logger)
@@ -1 +1,2 @@
1
1
  require_relative 'tasks/publish'
2
+ require_relative 'tasks/unpublish'
@@ -1,5 +1,5 @@
1
1
  module Contentful
2
2
  module Scheduler
3
- VERSION = "1.4.0"
3
+ VERSION = "1.5.0"
4
4
  end
5
5
  end
@@ -100,32 +100,6 @@ describe Contentful::Scheduler::Queue do
100
100
  end
101
101
  end
102
102
 
103
- describe '#already_published?' do
104
- it 'true if webhook publish_date is in past' do
105
- expect(subject.already_published?(
106
- WebhookDouble.new('bar', 'foo', {}, {'my_field' => '2011-04-04T22:00:00+00:00'})
107
- )).to be_truthy
108
- end
109
-
110
- it 'false if sys.publishedAt is in past' do
111
- expect(subject.already_published?(
112
- WebhookDouble.new('bar', 'foo', {'publishedAt' => '2011-04-04T22:00:00+00:00'}, {'my_field' => '2099-04-04T22:00:00+00:00'})
113
- )).to be_falsey
114
- end
115
-
116
- it 'false if sys.publishedAt is not present' do
117
- expect(subject.already_published?(
118
- WebhookDouble.new('bar', 'foo', {}, {'my_field' => '2099-04-04T22:00:00+00:00'})
119
- )).to be_falsey
120
- end
121
-
122
- it 'false if sys.publishedAt is present but nil' do
123
- expect(subject.already_published?(
124
- WebhookDouble.new('bar', 'foo', {'publishedAt' => nil}, {'my_field' => '2099-04-04T22:00:00+00:00'})
125
- )).to be_falsey
126
- end
127
- end
128
-
129
103
  describe '#publishable?' do
130
104
  it 'false if webhook space not present in config' do
131
105
  expect(subject.publishable?(
@@ -147,7 +121,7 @@ describe Contentful::Scheduler::Queue do
147
121
 
148
122
  it 'true if publish_field is populated' do
149
123
  expect(subject.publishable?(
150
- WebhookDouble.new('bar', 'foo', {}, {'my_field' => '2011-04-04T22:00:00+00:00'})
124
+ WebhookDouble.new('bar', 'foo', {}, {'my_field' => '2111-04-04T22:00:00+00:00'})
151
125
  )).to be_truthy
152
126
  end
153
127
  end
@@ -221,14 +195,6 @@ describe Contentful::Scheduler::Queue do
221
195
 
222
196
  subject.update_or_create(WebhookDouble.new('bar', 'foo', {}, {'my_field' => '2099-04-04T22:00:00+00:00'}))
223
197
  end
224
-
225
- it 'removes old call if already published' do
226
- allow(Resque).to receive(:peek) { [{'args' => ['foo', 'bar']}] }
227
- expect(Resque).not_to receive(:enqueue_at)
228
- expect(subject).to receive(:remove)
229
-
230
- subject.update_or_create(WebhookDouble.new('bar', 'foo', {}, {'my_field' => '2011-04-04T22:00:00+00:00'}))
231
- end
232
198
  end
233
199
  end
234
200
 
@@ -250,7 +216,7 @@ describe Contentful::Scheduler::Queue do
250
216
  allow(Resque).to receive(:peek) { [{'args' => ['foo', 'bar']}] }
251
217
  expect(Resque).to receive(:remove_delayed)
252
218
 
253
- subject.remove(WebhookDouble.new('bar', 'foo', {}, {'my_field' => '2011-04-04T22:00:00+00:00'}))
219
+ subject.remove(WebhookDouble.new('bar', 'foo', {}, {'my_field' => '2111-04-04T22:00:00+00:00'}))
254
220
  end
255
221
  end
256
222
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contentful-scheduler-custom
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Contentful GmbH (David Litvak Bruno0
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-24 00:00:00.000000000 Z
11
+ date: 2018-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contentful-webhook-listener
@@ -196,8 +196,8 @@ files:
196
196
  - README.md
197
197
  - Rakefile
198
198
  - contentful-scheduler.gemspec
199
+ - example/Dockerfile
199
200
  - example/Gemfile
200
- - example/Gemfile.lock
201
201
  - example/Procfile
202
202
  - example/Rakefile
203
203
  - example/config.ru
data/example/Gemfile.lock DELETED
@@ -1,83 +0,0 @@
1
- GEM
2
- remote: https://rubygems.org/
3
- specs:
4
- addressable (2.5.2)
5
- public_suffix (>= 2.0.2, < 4.0)
6
- chronic (0.10.2)
7
- contentful-management (1.10.0)
8
- http (> 1.0, < 3.0)
9
- json (~> 1.8)
10
- multi_json (~> 1)
11
- contentful-scheduler (0.2.1)
12
- chronic (~> 0.10)
13
- contentful-management (~> 1.8)
14
- contentful-webhook-listener (~> 0.2)
15
- redis (~> 3.0)
16
- resque (~> 1.0)
17
- resque-scheduler (~> 4.0)
18
- contentful-webhook-listener (0.3.0)
19
- domain_name (0.5.20170404)
20
- unf (>= 0.0.5, < 1.0.0)
21
- et-orbi (1.0.8)
22
- tzinfo
23
- http (2.2.2)
24
- addressable (~> 2.3)
25
- http-cookie (~> 1.0)
26
- http-form_data (~> 1.0.1)
27
- http_parser.rb (~> 0.6.0)
28
- http-cookie (1.0.3)
29
- domain_name (~> 0.5)
30
- http-form_data (1.0.3)
31
- http_parser.rb (0.6.0)
32
- json (1.8.6)
33
- mono_logger (1.1.0)
34
- multi_json (1.13.1)
35
- mustermann (1.0.1)
36
- public_suffix (3.0.1)
37
- rack (2.0.3)
38
- rack-protection (2.0.0)
39
- rack
40
- rake (12.3.0)
41
- redis (3.3.5)
42
- redis-namespace (1.6.0)
43
- redis (>= 3.0.4)
44
- resque (1.27.4)
45
- mono_logger (~> 1.0)
46
- multi_json (~> 1.0)
47
- redis-namespace (~> 1.3)
48
- sinatra (>= 0.9.2)
49
- vegas (~> 0.1.2)
50
- resque-scheduler (4.3.1)
51
- mono_logger (~> 1.0)
52
- redis (>= 3.3, < 5)
53
- resque (~> 1.26)
54
- rufus-scheduler (~> 3.2)
55
- rufus-scheduler (3.4.2)
56
- et-orbi (~> 1.0)
57
- sinatra (2.0.0)
58
- mustermann (~> 1.0)
59
- rack (~> 2.0)
60
- rack-protection (= 2.0.0)
61
- tilt (~> 2.0)
62
- thread_safe (0.3.6)
63
- tilt (2.0.8)
64
- tzinfo (1.2.4)
65
- thread_safe (~> 0.1)
66
- unf (0.1.4)
67
- unf_ext
68
- unf_ext (0.0.7.4)
69
- vegas (0.1.11)
70
- rack (>= 1.0.0)
71
-
72
- PLATFORMS
73
- ruby
74
-
75
- DEPENDENCIES
76
- contentful-management (~> 1.0)
77
- contentful-scheduler (~> 0.1)
78
- rake
79
- resque (~> 1.0)
80
- resque-scheduler (~> 4.0)
81
-
82
- BUNDLED WITH
83
- 1.16.1