singer-heroku 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a4f7cd180234a6480890663a4434f6d31225dd6e
4
+ data.tar.gz: c8079832fb851026ae94bad62f74db9d2421cf2b
5
+ SHA512:
6
+ metadata.gz: 92b3a846aa6ef35cacd35d49cb9e66c25ad4d4de9edf3fffab634f42c677159e17a7bf325c7fd5539644bbcef520da478c05fd80006f51464fe42d6e3320571a
7
+ data.tar.gz: 5898760849d0d1ada74a8ceb3d423cd77b34e8d35f16621e06d9abd5e8689c25ee733fccb24fa210ade659bcff2195d5bc4f5648f9f889b9324695d054f07f2f
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 follain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,46 @@
1
+ singer-heroku
2
+ =============
3
+
4
+ A collection of utilities to facilitate running [singer.io](http://singer.io)
5
+ taps and targets on Heroku
6
+
7
+ ## Installation
8
+
9
+ gem install singer-heroku
10
+
11
+
12
+ ## generate-config
13
+
14
+ Reads from `#{KEY}_CONFIG_*` environment variables and generates json to
15
+ stdout.
16
+
17
+ Given the following ENV:
18
+
19
+ TEST_CONFIG_first_name=joe
20
+ TEST_CONFIG_last_name=lind
21
+
22
+ generate-config -k TEST
23
+ {"first_name":"joe","last_name":"lind"}
24
+
25
+ ## read-state
26
+
27
+ Reads JSON `data` from `singer_states` table in `DATABASE_URL` where key is
28
+ `#{KEY}`, passed in args.
29
+
30
+ > read-state -kTEST
31
+ {"high_water_mark":4}
32
+
33
+
34
+ ## write-state
35
+
36
+ Reads jsonl from stdin and writes to database specified in DATABASE_URL
37
+
38
+ > cat states.json
39
+ { "high_water_mark": 1 }
40
+ { "high_water_mark": 2 }
41
+ { "high_water_mark": 3 }
42
+ { "high_water_mark": 4 }
43
+
44
+ > cat states.json | write-state -kTEST
45
+ > read-state -kTEST
46
+ {"high_water_mark":4}
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler'
4
+ Bundler.require
5
+
6
+ require 'optparse'
7
+ require_relative '../lib/generate_config'
8
+
9
+ config = nil
10
+
11
+ parser = OptionParser.new do |opts|
12
+ opts.banner = "Usage: #{$0} [options]"
13
+ opts.on('-k', '--key key', 'Config key prefix') do |key|
14
+ config = GenerateConfig.new(ENV.to_h.dup, key)
15
+ end
16
+
17
+ opts.on_tail('-h', '--help', 'Displays help') do
18
+ puts opts
19
+ exit
20
+ end
21
+ end
22
+
23
+ parser.parse!
24
+
25
+ unless config
26
+ puts parser
27
+ exit 1
28
+ end
29
+
30
+ puts config.to_json
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler'
5
+ Bundler.require
6
+
7
+ require 'optparse'
8
+ require_relative '../lib/database'
9
+ require_relative '../lib/read_state'
10
+ require 'dotenv/load'
11
+ require 'logger'
12
+
13
+ read_state = nil
14
+ database = Database.new(ENV.fetch('DATABASE_URL'))
15
+
16
+ parser = OptionParser.new do |opts|
17
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
18
+ opts.on('-k', '--key key', 'Config key prefix') do |key|
19
+ read_state = ReadState.new(key, database)
20
+ end
21
+
22
+ opts.on_tail('-v', '--verbose', 'Enable verbose logging') do
23
+ database.logger = Logger.new($stderr)
24
+ end
25
+
26
+ opts.on_tail('-h', '--help', 'Displays help') do
27
+ puts opts
28
+ exit
29
+ end
30
+ end
31
+
32
+ parser.parse!
33
+
34
+ unless read_state
35
+ puts parser
36
+ exit 1
37
+ end
38
+
39
+ puts JSON.generate(read_state.perform)
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler'
5
+ Bundler.require
6
+
7
+ require 'optparse'
8
+ require 'logger'
9
+ require_relative '../lib/database'
10
+ require_relative '../lib/write_state'
11
+ require 'dotenv/load'
12
+
13
+ write_state = nil
14
+ database = Database.new(ENV.fetch('DATABASE_URL'))
15
+
16
+ parser = OptionParser.new do |opts|
17
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
18
+ opts.on('-k', '--key key', 'Config key prefix') do |key|
19
+ write_state = WriteState.new(key, database)
20
+ end
21
+
22
+ opts.on_tail('-v', '--verbose', 'Enable verbose logging') do
23
+ database.logger = Logger.new($stderr)
24
+ end
25
+
26
+ opts.on_tail('-h', '--help', 'Displays help') do
27
+ puts opts
28
+ exit
29
+ end
30
+ end
31
+
32
+ parser.parse!
33
+
34
+ unless write_state
35
+ puts parser
36
+ exit 1
37
+ end
38
+
39
+ while STDIN.gets
40
+ state = $LAST_READ_LINE.chomp
41
+ write_state.perform JSON.parse(state)
42
+ end
@@ -0,0 +1,20 @@
1
+
2
+ # frozen_string_literal: true
3
+
4
+ require 'sequel'
5
+
6
+ Database = Struct.new(:url) do
7
+ def db
8
+ @db ||= Sequel.connect(url).tap do |db|
9
+ db.extension :pg_json
10
+ end
11
+ end
12
+
13
+ def states
14
+ db[:singer_states]
15
+ end
16
+
17
+ def logger=(logger)
18
+ db.loggers = [logger]
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ GenerateConfig = Struct.new(:env, :key) do
6
+ def key_pattern
7
+ /^#{key}_CONFIG_(.+)/
8
+ end
9
+
10
+ def to_json
11
+ JSON.generate(values)
12
+ end
13
+
14
+ def values
15
+ Hash[
16
+ env.keys.grep(key_pattern).map do |key|
17
+ [
18
+ key.match(key_pattern)[1],
19
+ cast_if_needed(env[key])
20
+ ]
21
+ end
22
+ ]
23
+ end
24
+
25
+ private
26
+
27
+ def cast_if_needed(value)
28
+ return value.to_i if value.to_i.to_s == value
29
+ return value.to_f if value.to_f.to_s == value
30
+
31
+ value
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+
5
+ module SingerHeroku
6
+ # Rake tasks for migrating development database
7
+ class RakeTasks
8
+ include Rake::DSL if defined? Rake::DSL
9
+
10
+ # rubocop:disable Rails/Output
11
+ def install_tasks
12
+ namespace :singer_heroku do
13
+ desc 'Run migrations'
14
+ task :migrate, [:version] do |_t, args|
15
+ Sequel.extension :migration
16
+ db = Sequel.connect(ENV.fetch('DATABASE_URL'))
17
+ version = args[:version]
18
+ puts "Migrating to #{version || 'latest'}"
19
+ version = version&.to_i
20
+ Sequel::Migrator.run(db, 'db/migrations', target: version)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ SingerHeroku::RakeTasks.new.install_tasks
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ ReadState = Struct.new(:key, :database) do
4
+ def perform
5
+ record = database.states.where(key: key).first
6
+ return record[:data] if record
7
+ {}
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SingerHeroku
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ WriteState = Struct.new(:key, :database) do
4
+ def perform(value)
5
+ insert.call key: key, data: Sequel.pg_json(value)
6
+ end
7
+
8
+ private
9
+
10
+ def insert
11
+ @insert ||= database
12
+ .states
13
+ .insert_conflict(
14
+ target: :key, update: { data: Sequel[:excluded][:data] }
15
+ )
16
+ .prepare(:insert, :insert_state, key: :$key, data: :$data)
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: singer-heroku
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Joe Lind
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-06-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pg
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.21'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.21'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sequel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.49'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.49'
55
+ description: " Creates config files from ENV; Read/writes state from postgres database\n"
56
+ email: joelind@gmail.com
57
+ executables:
58
+ - generate-config
59
+ - read-state
60
+ - write-state
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - LICENSE
65
+ - README.md
66
+ - bin/generate-config
67
+ - bin/read-state
68
+ - bin/write-state
69
+ - lib/database.rb
70
+ - lib/generate_config.rb
71
+ - lib/rake_tasks.rb
72
+ - lib/read_state.rb
73
+ - lib/singer_heroku/version.rb
74
+ - lib/write_state.rb
75
+ homepage: https://github.com/Follain/singer-heroku
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.5.2
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Singer.io utilities for executing on Heroku
99
+ test_files: []