cocoapods-humus 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: daab17c7e517f60d47fa75b650e3d29dccc46e52
4
+ data.tar.gz: dd4bff6f4b532dcc9067acc1e174f2cfff18ad58
5
+ SHA512:
6
+ metadata.gz: d71c2a34692f264ec7c843124b3cf32974529bb40bce1eabcc1bd7f345e29183739da244dad52c8493d635fa44a0fdf31a8492e06f1788b0b50436a3b7d22473
7
+ data.tar.gz: 273b8ec6c8fe5e1d9abbfab156400a9f71052737ca710aab103862b4758549ddace41862e91e86c8a17279868cc51b70a75de5b26ccb035ce23389361b38fbab
@@ -0,0 +1 @@
1
+ Sanitized trunk dumps are downloaded into this directory (repo or gem).
@@ -0,0 +1,76 @@
1
+ require File.expand_path('../snapshots', __FILE__)
2
+
3
+ # Helper module for all projects in Strata that need
4
+ # Database access and management.
5
+ #
6
+ # Load this in Strata via '../Humus/lib/cocoapods-humus'.
7
+ # Then use the Humus helper methods:
8
+ # * Humus.with_snapshot(name, options = {})
9
+ #
10
+ module Humus
11
+
12
+ # Load a specific snapshot into the database.
13
+ #
14
+ # Use this in integration tests in a CP project.
15
+ #
16
+ # For this to work,
17
+ # ENV['DUMP_ACCESS_KEY_ID']
18
+ # ENV['DUMP_SECRET_ACCESS_KEY']
19
+ # need to be set.
20
+ #
21
+ # Note: Does not ROLLBACK yet!
22
+ #
23
+ # @param [String] name The name of the snapshot.
24
+ # @param [Hash] options Options: env, seed, rollback (not implemented yet).
25
+ #
26
+ # @example
27
+ # Humus.with_snapshot('b008') do
28
+ # # Do something for which you need snapshot b008.
29
+ # end
30
+ #
31
+ def self.with_snapshot name, options = {}
32
+ environment = options[:env] || ENV['RACK_ENV'] || 'test'
33
+ seed = options[:seed] || true
34
+ rollback = options[:rollback] && raise("Option :rollback not implemented yet.")
35
+
36
+ # Currently, we only want this for tests.
37
+ #
38
+ return unless environment == 'test'
39
+
40
+ # If seed is falsy, just yield.
41
+ #
42
+ if seed
43
+ access_key_id = ENV['DUMP_ACCESS_KEY_ID']
44
+ secret_access_key = ENV['DUMP_SECRET_ACCESS_KEY']
45
+ unless access_key_id && secret_access_key
46
+ raise 'Set both DUMP_ACCESS_KEY_ID and DUMP_SECRET_ACCESS_KEY in ENV.'
47
+ end
48
+
49
+ snapshots = Snapshots.new(access_key_id, secret_access_key)
50
+ begin
51
+ # Seed from dump.
52
+ #
53
+ snapshots.seed_from_dump(name)
54
+
55
+ # All good. Call the code that needs the snapshot.
56
+ #
57
+ block_given? && yield
58
+ rescue RuntimeError => e # TODO Be more specific.
59
+ unless @retried
60
+ p e
61
+
62
+ # Load snapshot.
63
+ snapshots.download_prepared_dump(name)
64
+
65
+ # And retry to seed.
66
+ #
67
+ retry
68
+ end
69
+ @retried = true
70
+ end
71
+ else
72
+ block_given? && yield
73
+ end
74
+ end
75
+
76
+ end
data/lib/snapshots.rb ADDED
@@ -0,0 +1,117 @@
1
+ module Humus
2
+
3
+ # Helper class for downloading/seeding dumps.
4
+ #
5
+ class Snapshots
6
+
7
+ attr_reader :access_key_id
8
+ attr_reader :secret_access_key
9
+
10
+ def initialize access_key_id = nil, secret_access_key = nil
11
+ @access_key_id = access_key_id
12
+ @secret_access_key = secret_access_key
13
+ end
14
+
15
+ # Download prepared dump from S3 (needs credentials).
16
+ #
17
+ def download_prepared_dump id
18
+ name = "trunk-#{id}.dump"
19
+ target_path = File.expand_path("../../fixtures/#{name}", __FILE__)
20
+
21
+ puts "Accessing prepared DB test snapshot #{id} from S3."
22
+
23
+ require 's3'
24
+ service = S3::Service.new(:access_key_id => access_key_id, :secret_access_key => secret_access_key)
25
+ bucket = service.buckets.find("cocoapods-org-testing-dumps")
26
+
27
+ # Due to a bug in the s3 gem we are searching for the object via iterating.
28
+ bucket.objects.each do |obj|
29
+ if obj.key == name
30
+ puts "Downloading prepared DB test snapshot #{id} from S3."
31
+ File.open(target_path, 'w') do |file|
32
+ file.write(obj.content)
33
+ end
34
+ break
35
+ end
36
+ end
37
+
38
+ puts "Prepared DB test snapshot #{id} downloaded to #{target_path}"
39
+ end
40
+
41
+ # Seed the database from a downloaded dump.
42
+ #
43
+ def seed_from_dump id
44
+ target_path = File.expand_path("../../fixtures/trunk-#{id}.dump", __FILE__)
45
+ raise "Dump #{id} could not be found." unless File.exists? target_path
46
+
47
+ puts "Restoring #{ENV['RACK_ENV']} database from #{target_path}"
48
+
49
+ # Ensure we're starting from a clean DB.
50
+ system "dropdb trunk_cocoapods_org_test"
51
+ system "createdb trunk_cocoapods_org_test"
52
+
53
+ # Restore the DB.
54
+ command = "pg_restore --no-privileges --clean --no-acl --no-owner -h localhost -d trunk_cocoapods_org_test #{target_path}"
55
+ puts "Executing:"
56
+ puts command
57
+ puts
58
+ result = system command
59
+ if result
60
+ puts "Database #{ENV['RACK_ENV']} restored from #{target_path}"
61
+ else
62
+ warn "Database #{ENV['RACK_ENV']} restored from #{target_path} with some errors."
63
+ # exit 1
64
+ end
65
+ end
66
+
67
+ # Dump the production DB.
68
+ #
69
+ # TODO Also create a sanitized dump and upload to S3? (For now, we can do it manually)
70
+ #
71
+ # Preparing a dump.
72
+ #
73
+ # 1. Make a snapshot on Heroku.
74
+ # 2. SQL:
75
+ # create or replace function random_string(length integer) returns text as
76
+ # $$
77
+ # declare
78
+ # chars text[] := '{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}';
79
+ # result text := '';
80
+ # i integer := 0;
81
+ # begin
82
+ # if length < 0 then
83
+ # raise exception 'Given length cannot be less than 0';
84
+ # end if;
85
+ # for i in 1..length loop
86
+ # result := result || chars[1+random()*(array_length(chars, 1)-1)];
87
+ # end loop;
88
+ # return result;
89
+ # end;
90
+ # $$ language plpgsql;
91
+ #
92
+ # UPDATE owners
93
+ # SET
94
+ # name = concat(random_string(1), lower(random_string(5)), ' ', random_string(1), lower(random_string(7))),
95
+ # email = lower(concat(random_string(15), '@', random_string(10), '.', random_string(3)))
96
+ # TRUNCATE TABLE sessions;
97
+ #
98
+ # 3. Run
99
+ # $ pg_dump -Fc trunk_cocoapods_org_test > fixtures/trunk-<date>-<Heroku snapshot id>.dump
100
+ #
101
+ def dump_prod id
102
+ target_path = File.expand_path("../../fixtures/trunk-#{id}.dump", __FILE__)
103
+ puts "Dumping production database from Heroku (works only if you have access to the database)"
104
+ command = "curl -o #{target_path} \`heroku pg:backups public-url #{id} -a cocoapods-trunk-service\`"
105
+ puts "Executing command:"
106
+ puts command
107
+ result = system command
108
+ if result
109
+ puts "Production database snapshot #{id} dumped into #{target_path}"
110
+ else
111
+ raise "Could not dump #{id} from production database."
112
+ end
113
+ end
114
+
115
+ end
116
+
117
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cocoapods-humus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Florian Hanke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: s3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.3'
27
+ description: CocoaPods database helper gem.
28
+ email: florian.hanke+cocoapods.org@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - fixtures/README.md
34
+ - lib/cocoapods-humus.rb
35
+ - lib/snapshots.rb
36
+ homepage: https://github.com/CocoaPods/Humus
37
+ licenses:
38
+ - MIT
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project:
56
+ rubygems_version: 2.2.2
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: Manages DB dumps for testing.
60
+ test_files: []
61
+ has_rdoc: