is_it_done_yet 0.2.0 → 0.3.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: 1778acaba096d60e74ad95e7fae02e11a0a8cec0
4
- data.tar.gz: 1fa88b4da2deae3f11f31765d86c7478ef2a6108
3
+ metadata.gz: acd12c54ad56816b78a4dce97b4959ca75f13392
4
+ data.tar.gz: 61d989bd6096d96b479d17b0823d360d8e374824
5
5
  SHA512:
6
- metadata.gz: 0a14bcf35ad70e435d7a817a7a6f8f05b2292f82f5fc385135ac69778a0509940175222f9880f1fc403541b077bd13757edca2db19ae94860726e31dd71b58bb
7
- data.tar.gz: 1ef23febcd56156d6c72ec677f661da926102d6e9043e9f1ae3912ef53ce1a19deeb16b98af72648530e0954706a273f76efedd064b89e62356032e468793274
6
+ metadata.gz: 5e90bcdbe755b2430d43f1e3f9e4579e5ed262beeeb7eb0179aa0dad1531c6683a8ecbfc6cf8d56fdb286e2d451e176e7759cca98910a933147ccd41c82d8cb1
7
+ data.tar.gz: a13eb75011f38fe0492df830e8f7a7a5a3d0c8cbc9816c08c7bfb548acb35a79a847454c1bd7acc68a4a755bf3c5817799dce0225af87a78151d0e75dbc41ba3
data/.gitignore CHANGED
@@ -11,3 +11,4 @@
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
13
  *.gem
14
+ .byebug_history
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # 0.3.0
2
+
3
+ Features:
4
+
5
+ * Clear state for a build using `DELETE /builds/:build_id`. Useful when a CI build is restarted.
6
+
7
+ Bug fixes:
8
+
9
+ * Posting now adheres to standard REST conventions; returns 201 with no body if successful and 409 if the node already exists.
10
+
11
+
1
12
  # 0.2.0
2
13
 
3
14
  Features:
data/Rakefile CHANGED
@@ -1,10 +1,9 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
  require 'knapsack'
4
4
 
5
-
6
5
  RSpec::Core::RakeTask.new(:spec)
7
6
 
8
- task :default => :spec
7
+ task default: :spec
9
8
 
10
9
  Knapsack.load_tasks if defined?(Knapsack)
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "is_it_done_yet"
3
+ require 'bundler/setup'
4
+ require 'is_it_done_yet'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "is_it_done_yet"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
data/examples/ci-clear ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Script that clears build status of
4
+ # travis nodes from synchronising service
5
+
6
+ require 'net/http'
7
+ require 'uri'
8
+ require 'json'
9
+
10
+ SLEEP_TIME_SECONDS = 30
11
+
12
+ env_ok = ENV['CI_NODE_INDEX'] &&
13
+ ENV['CI_NODE_TOTAL'] &&
14
+ ENV['IIDY_ENDPOINT'] &&
15
+ ENV['TRAVIS_BUILD_NUMBER'] &&
16
+ ENV['TRAVIS_JOB_NUMBER'] &&
17
+ ENV['IIDY_TOKEN']
18
+
19
+ abort 'Bad env' unless env_ok
20
+
21
+ main_node = ENV['CI_NODE_INDEX'] == '0'
22
+ auth_token = "Token token=\"#{ENV['IIDY_TOKEN']}\""
23
+
24
+ if main_node
25
+ build_id = "is_it_done_yet--#{ENV['TRAVIS_BUILD_NUMBER']}"
26
+
27
+ url = ENV['IIDY_ENDPOINT'] + "/builds/#{build_id}"
28
+
29
+ puts "URL: #{url}"
30
+
31
+ uri = URI(url)
32
+
33
+ request = Net::HTTP::Delete.new(uri)
34
+ request['Authorization'] = auth_token
35
+
36
+ response = Net::HTTP.start(
37
+ uri.hostname,
38
+ uri.port,
39
+ use_ssl: uri.scheme == 'https'
40
+ ) { |http| http.request(request) }
41
+
42
+ abort 'Failed to clear results' unless response.code == '204'
43
+ puts 'Successfully cleared results!'
44
+ else
45
+ puts 'Not main node!'
46
+ end
data/examples/ci-post CHANGED
@@ -46,5 +46,5 @@ else
46
46
  use_ssl: uri.scheme == 'https'
47
47
  ) { |http| http.request(request) }
48
48
 
49
- abort "Failed to post build status: #{response.code}" unless response.code == '200'
49
+ abort "Failed to post build status: #{response.code}" unless response.code == '201'
50
50
  end
data/examples/ci-sync CHANGED
@@ -8,7 +8,7 @@ require 'net/http'
8
8
  require 'uri'
9
9
  require 'json'
10
10
 
11
- OK_STATES = %w(OK GOOD).freeze
11
+ OK_STATES = %w[OK GOOD].freeze
12
12
  SLEEP_TIME_SECONDS = 30
13
13
 
14
14
  env_ok = ENV['CI_NODE_INDEX'] &&
@@ -52,13 +52,17 @@ if main_node
52
52
  use_ssl: uri.scheme == 'https'
53
53
  ) { |http| http.request(request) }
54
54
 
55
- next unless response.code == '200'
55
+ unless response.code == '200'
56
+ sleep SLEEP_TIME_SECONDS
57
+ next
58
+ end
59
+
56
60
  build_states = JSON.parse(response.body)['build_states']
57
61
 
58
62
  if build_states.size < expected_size
59
63
  puts "Some nodes have not reported in yet, \
60
- found #{build_states.size}, \
61
- expected #{expected_size}, waiting a bit"
64
+ found #{build_states.size}, \
65
+ expected #{expected_size}, waiting a bit"
62
66
  sleep SLEEP_TIME_SECONDS
63
67
  next
64
68
  end
data/examples/config.ru CHANGED
@@ -4,8 +4,14 @@ require 'rack/token_auth'
4
4
  require 'is_it_done_yet'
5
5
  Bundler.require
6
6
 
7
- use Rack::TokenAuth do |token, options, env|
7
+ # Shared secret authentication
8
+ use Rack::TokenAuth do |token, _options, _env|
8
9
  token == ENV['IIDY_TOKEN']
9
10
  end
10
11
 
12
+ # Heartbeat endpoint
13
+ map '/health_check' do
14
+ run ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['success']] }
15
+ end
16
+
11
17
  run IsItDoneYet.build_app
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'is_it_done_yet/version'
@@ -46,4 +47,5 @@ Gem::Specification.new do |spec|
46
47
  spec.add_development_dependency 'rspec', '~> 3.0'
47
48
  spec.add_development_dependency 'rack-test', '~> 0.6'
48
49
  spec.add_development_dependency 'knapsack', '~> 1.13'
50
+ spec.add_development_dependency 'byebug', '~> 9'
49
51
  end
@@ -1,96 +1,9 @@
1
1
  require 'is_it_done_yet/version'
2
- require 'sinatra'
3
- require 'concurrent'
4
- require 'json'
5
- require 'time'
2
+ require 'is_it_done_yet/web_app'
6
3
  require 'rack/contrib'
4
+ require 'rack'
7
5
 
8
6
  module IsItDoneYet
9
- class WebApp < ::Sinatra::Base
10
- UNKNOWN_NODE = { errors: ['Unknown Node'] }.to_json
11
- UNKNOWN_BUILD = { errors: ['Unknown Build'] }.to_json
12
- NO_BUILD_STATE = { errors: ['You forgot build state'] }.to_json
13
- TTL_SECONDS = 24 * 60 * 60
14
-
15
- configure do
16
- set :state, ::Concurrent::Map.new
17
- end
18
-
19
- helpers do
20
- private
21
-
22
- def key(build_id, node_id)
23
- [build_id, node_id].freeze
24
- end
25
-
26
- def house_keeping
27
- expired_keys =
28
- settings.state.each_pair.with_object([]) do |(key, (_b, time)), acc|
29
- acc << key if time < Time.now - TTL_SECONDS
30
- end
31
-
32
- expired_keys.each { |key| settings.state.delete(key) }
33
- end
34
-
35
- def store(key, value)
36
- settings.state[key] = [value, Time.now]
37
- end
38
-
39
- def retrieve(key)
40
- build_state, _t = settings.state[key]
41
- build_state
42
- end
43
-
44
- def retrieve_all(build_id)
45
- settings.state
46
- .each_pair
47
- .select { |((b, _n), _v)| build_id == b }
48
- .map { |((_b, node_id), (build_state, _t))| [node_id, build_state] }
49
- .to_h
50
- end
51
- end
52
-
53
- before do
54
- house_keeping
55
-
56
- content_type :json
57
- end
58
-
59
- get '/builds/:build_id/nodes/:node_id' do
60
- build_id, node_id = params.values_at('build_id', 'node_id')
61
- k = key(build_id, node_id)
62
-
63
- build_state = retrieve(k)
64
-
65
- halt 404, UNKNOWN_NODE unless build_state
66
-
67
- content_type :json
68
- { build_state: build_state }.to_json
69
- end
70
-
71
- get '/builds/:build_id' do
72
- build_id = params['build_id']
73
-
74
- build_states = retrieve_all(build_id)
75
-
76
- halt 404, UNKNOWN_BUILD if build_states.to_a.empty?
77
-
78
- content_type :json
79
- { build_states: build_states }.to_json
80
- end
81
-
82
- post '/builds/:build_id/nodes/:node_id' do
83
- build_state = params['build_state']
84
- halt 400, NO_BUILD_STATE unless build_state
85
-
86
- build_id, node_id = params.values_at('build_id', 'node_id')
87
- k = key(build_id, node_id)
88
- store(k, build_state)
89
-
90
- 200
91
- end
92
- end
93
-
94
7
  def self.build_app
95
8
  Rack::Builder.app do
96
9
  use Rack::PostBodyContentTypeParser
@@ -1,3 +1,3 @@
1
1
  module IsItDoneYet
2
- VERSION = "0.2.0"
2
+ VERSION = '0.3.0'.freeze
3
3
  end
@@ -0,0 +1,108 @@
1
+ require 'is_it_done_yet/version'
2
+ require 'sinatra'
3
+ require 'concurrent'
4
+ require 'json'
5
+ require 'time'
6
+ require 'rack/contrib'
7
+
8
+ module IsItDoneYet
9
+ class WebApp < ::Sinatra::Base
10
+ UNKNOWN_NODE = { errors: ['Unknown Node'] }.to_json
11
+ ALREADY_EXISTS = { errors: ['Node already exists'] }.to_json
12
+ UNKNOWN_BUILD = { errors: ['Unknown Build'] }.to_json
13
+ NO_BUILD_STATE = { errors: ['You forgot build state'] }.to_json
14
+ TTL_SECONDS = 24 * 60 * 60
15
+
16
+ configure do
17
+ set :state, ::Concurrent::Map.new
18
+ end
19
+
20
+ helpers do
21
+ private
22
+
23
+ def key(build_id, node_id)
24
+ [build_id, node_id].freeze
25
+ end
26
+
27
+ def house_keeping
28
+ expired_keys =
29
+ settings.state.each_pair.with_object([]) do |(key, (_b, time)), acc|
30
+ acc << key if time < Time.now - TTL_SECONDS
31
+ end
32
+
33
+ expired_keys.each { |key| settings.state.delete(key) }
34
+ end
35
+
36
+ def store(key, value)
37
+ settings.state[key] = [value, Time.now]
38
+ end
39
+
40
+ def retrieve(key)
41
+ build_state, _t = settings.state[key]
42
+ build_state
43
+ end
44
+
45
+ def retrieve_all(build_id)
46
+ settings.state
47
+ .each_pair
48
+ .select { |((b, _n), _v)| build_id == b }
49
+ .map { |((_b, node_id), (build_state, _t))| [node_id, build_state] }
50
+ .to_h
51
+ end
52
+
53
+ def clear_nodes(build_id)
54
+ state = settings.state
55
+ keys_for_build = state.keys.select { |(b, _n)| b == build_id }
56
+ keys_for_build.each { |key| state.delete(key) }
57
+ end
58
+ end
59
+
60
+ before do
61
+ house_keeping
62
+
63
+ content_type :json
64
+ end
65
+
66
+ get '/builds/:build_id/nodes/:node_id' do
67
+ build_id, node_id = params.values_at('build_id', 'node_id')
68
+ k = key(build_id, node_id)
69
+
70
+ build_state = retrieve(k)
71
+
72
+ halt 404, UNKNOWN_NODE unless build_state
73
+
74
+ { build_state: build_state }.to_json
75
+ end
76
+
77
+ get '/builds/:build_id' do
78
+ build_id = params['build_id']
79
+
80
+ build_states = retrieve_all(build_id)
81
+
82
+ halt 404, UNKNOWN_BUILD if build_states.to_a.empty?
83
+
84
+ { build_states: build_states }.to_json
85
+ end
86
+
87
+ delete '/builds/:build_id' do
88
+ build_id = params['build_id']
89
+
90
+ clear_nodes(build_id)
91
+
92
+ 204
93
+ end
94
+
95
+ post '/builds/:build_id/nodes/:node_id' do
96
+ build_state = params['build_state']
97
+ halt 400, NO_BUILD_STATE unless build_state
98
+
99
+ build_id, node_id = params.values_at('build_id', 'node_id')
100
+ k = key(build_id, node_id)
101
+ halt 409, ALREADY_EXISTS if retrieve(k)
102
+
103
+ store(k, build_state)
104
+
105
+ 201
106
+ end
107
+ end
108
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: is_it_done_yet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Madsen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-23 00:00:00.000000000 Z
11
+ date: 2017-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '1.13'
167
+ - !ruby/object:Gem::Dependency
168
+ name: byebug
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '9'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '9'
167
181
  description: In case you need to carry out build steps in one of the nodes of your
168
182
  CI project after the other nodes finish, e.g. deploying, then you need a way of
169
183
  ascertaining the status of the other nodes. This is what is_it_done_yet is for.
@@ -183,6 +197,7 @@ files:
183
197
  - Rakefile
184
198
  - bin/console
185
199
  - bin/setup
200
+ - examples/ci-clear
186
201
  - examples/ci-deploy
187
202
  - examples/ci-post
188
203
  - examples/ci-sync
@@ -190,6 +205,7 @@ files:
190
205
  - is_it_done_yet.gemspec
191
206
  - lib/is_it_done_yet.rb
192
207
  - lib/is_it_done_yet/version.rb
208
+ - lib/is_it_done_yet/web_app.rb
193
209
  homepage: http://www.github.com/beatmadsen/is_it_done_yet
194
210
  licenses:
195
211
  - MIT