prick 0.29.2 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/TODO +2 -0
- data/exe/prick +290 -518
- data/lib/prick/builder/batch.rb +1 -4
- data/lib/prick/builder/builder.rb +15 -9
- data/lib/prick/builder/node.rb +3 -2
- data/lib/prick/builder/node_pool.rb +3 -1
- data/lib/prick/builder/parser.rb +2 -1
- data/lib/prick/constants.rb +12 -12
- data/lib/prick/diff.rb +2 -2
- data/lib/prick/environment.rb +23 -10
- data/lib/prick/local/command.rb +8 -2
- data/lib/prick/local/fmt.rb +56 -0
- data/lib/prick/prick_version.rb +1 -1
- data/lib/prick/share/init/{.gitignore → dot.gitignore} +1 -1
- data/lib/prick/share/init/prick.environment.yml +16 -0
- data/lib/prick/share/init/prick.yml +3 -3
- data/lib/prick/share/init/schema/prick/build.yml +11 -2
- data/lib/prick/share/init/schema/prick/tables.sql +30 -9
- data/lib/prick/share/init/schema/prick/views.sql +6 -0
- data/lib/prick/state.rb +297 -95
- data/lib/prick/subcommand/prick-build.rb +26 -20
- data/lib/prick/subcommand/prick-clean.rb +5 -5
- data/lib/prick/subcommand/prick-create.rb +41 -6
- data/lib/prick/subcommand/prick-drop.rb +57 -14
- data/lib/prick/subcommand/prick-fox.rb +1 -1
- data/lib/prick/subcommand/prick-init.rb +25 -18
- data/lib/prick/subcommand/prick-list.rb +99 -0
- data/lib/prick/subcommand/prick-make.rb +8 -8
- data/lib/prick/subcommand/prick-migrate.rb +8 -7
- data/lib/prick/subcommand/prick-release.rb +4 -2
- data/lib/prick/subcommand/prick-set.rb +52 -0
- data/lib/prick/subcommand/prick-setup.rb +3 -13
- data/lib/prick/subcommand/prick-teardown.rb +13 -9
- data/lib/prick/subcommand/subcommand.rb +12 -0
- data/lib/prick/version.rb +1 -1
- data/lib/prick.rb +54 -15
- metadata +9 -5
- data/lib/prick/share/init/schema/prick/data.sql +0 -6
- data/prick.environments.yml +0 -14
data/lib/prick/builder/batch.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Prick
|
2
2
|
module Build
|
3
3
|
class BuildBatch
|
4
|
-
include
|
4
|
+
include Timer
|
5
5
|
|
6
6
|
attr_reader :builder
|
7
7
|
forward_to :builder, :conn
|
@@ -144,9 +144,6 @@ module Prick
|
|
144
144
|
delete = builder.clean ? :none : :touched
|
145
145
|
begin
|
146
146
|
conn.execute fox.to_sql(format: :exec, delete: delete)
|
147
|
-
|
148
|
-
# FIXME: Why only in FoxBatch - should be set higher up in the system
|
149
|
-
conn.execute "update prick.versions set built_at = now() at time zone 'UTC'"
|
150
147
|
rescue PG::SyntaxError, PG::Error => ex
|
151
148
|
raise PostgresError.new(ex.message)
|
152
149
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '../local/command'
|
1
|
+
require_relative '../local/command.rb'
|
2
2
|
|
3
3
|
require_relative './node.rb'
|
4
4
|
require_relative './node_pool.rb'
|
@@ -103,18 +103,24 @@ module Prick
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def execute(conn, create_schemas: schemas)
|
106
|
+
# Group batches
|
106
107
|
group if batches.nil?
|
108
|
+
|
109
|
+
# Register build in database
|
110
|
+
Prick.state.save_build_begin
|
111
|
+
|
112
|
+
# Create schemas
|
107
113
|
conn.exec create_schemas.map { |schema| "create schema #{schema}" }
|
108
|
-
for batch in batches
|
109
|
-
batch.execute
|
110
|
-
end
|
111
|
-
end
|
112
114
|
|
113
|
-
#
|
114
|
-
|
115
|
+
# Execute batch groups
|
116
|
+
t0 = Time.now
|
117
|
+
batches.each(&:execute)
|
118
|
+
t1 = Time.now
|
115
119
|
|
116
|
-
#
|
117
|
-
|
120
|
+
# Register build result in database
|
121
|
+
dt = t1 - t0
|
122
|
+
Prick.state.save_build_end(true, dt)
|
123
|
+
end
|
118
124
|
|
119
125
|
def dump
|
120
126
|
batches ? batches.each(&:dump) : pool.dump
|
data/lib/prick/builder/node.rb
CHANGED
@@ -140,7 +140,7 @@ module Prick
|
|
140
140
|
Command.command(Prick.state.bash_environment, command)
|
141
141
|
rescue Command::Error => ex
|
142
142
|
message = "Error executing '#{command}'\n" + ex.stderr.map { |l| " #{l}" }.join("\n")
|
143
|
-
|
143
|
+
Prick.error message
|
144
144
|
end
|
145
145
|
end
|
146
146
|
end
|
@@ -188,12 +188,13 @@ module Prick
|
|
188
188
|
puts "BuildNode #{path}"
|
189
189
|
indent {
|
190
190
|
puts "schema: #{schema}" if schema
|
191
|
+
puts "refresh: #{refresh_schema.to_s}"
|
191
192
|
puts "pg_graph_ignore_schema: #{pg_graph_ignore_schema}"
|
192
193
|
decl_nodes.each(&:dump)
|
193
194
|
for kind in [:init, :term, :seed]
|
194
195
|
kind_nodes = self.send("#{kind}_nodes".to_sym)
|
195
196
|
if !kind_nodes.empty?
|
196
|
-
puts "#{kind
|
197
|
+
puts "#{kind}:"
|
197
198
|
indent { kind_nodes.each(&:dump) }
|
198
199
|
end
|
199
200
|
end
|
@@ -25,7 +25,7 @@ module Prick
|
|
25
25
|
def build_nodes() nodes.select { |node| node.is_a?(BuildNode) } end
|
26
26
|
|
27
27
|
# List of schemas to ignore when building PgGraph objects. This is used
|
28
|
-
# to exclude foreign
|
28
|
+
# to exclude foreign schemas that doesn't follow the PgGraph naming
|
29
29
|
# conventions
|
30
30
|
def pg_graph_ignore_schemas()
|
31
31
|
all_nodes.select { |node|
|
@@ -33,6 +33,8 @@ module Prick
|
|
33
33
|
}.map(&:schema).uniq
|
34
34
|
end
|
35
35
|
|
36
|
+
# List of schemas that should be rebuilt. #refresh_schemas is not cached
|
37
|
+
# and can be manipulated by removing build nodes from the pool
|
36
38
|
def refresh_schemas()
|
37
39
|
build_nodes.select(&:refresh_schema).map(&:schema).uniq
|
38
40
|
end
|
data/lib/prick/builder/parser.rb
CHANGED
@@ -130,7 +130,8 @@ module Prick
|
|
130
130
|
rest = $3
|
131
131
|
args = expand_string(rest || '').split
|
132
132
|
path = expand_filename(dir, command)
|
133
|
-
path || optional or
|
133
|
+
path || optional or
|
134
|
+
raise Error, "Can't find file\n #{command}\n #{path}\n in #{dir}/\n from #{unit}"
|
134
135
|
!path.nil? or return nil
|
135
136
|
else
|
136
137
|
raise Error, "Not a file name: '#{entry}'"
|
data/lib/prick/constants.rb
CHANGED
@@ -7,8 +7,8 @@ module Prick
|
|
7
7
|
### DIRECTORIES AND FILE NAMES
|
8
8
|
|
9
9
|
# Shared files (part of the installation)
|
10
|
-
SHARE_PATH = "#{File.dirname(File.dirname(__dir__))}/lib/share"
|
11
|
-
LIBEXEC_PATH = "#{File.dirname(File.dirname(__dir__))}/lib/libexec"
|
10
|
+
SHARE_PATH = "#{File.dirname(File.dirname(__dir__))}/lib/prick/share"
|
11
|
+
LIBEXEC_PATH = "#{File.dirname(File.dirname(__dir__))}/lib/prick/libexec"
|
12
12
|
|
13
13
|
# Project directories
|
14
14
|
DIRS = [
|
@@ -30,19 +30,19 @@ module Prick
|
|
30
30
|
PRICK_DIR = Dir.getwd
|
31
31
|
|
32
32
|
# Search path for executables
|
33
|
-
|
33
|
+
# PRICK_PATH = "#{ENV['PATH']}:#{PRICK_DIR}/#{BIN_DIR}:#{PRICK_DIR}/#{LIBEXEC_DIR}"
|
34
34
|
|
35
|
-
# Project
|
35
|
+
# Project file
|
36
36
|
PRICK_PROJECT_FILE = "prick.yml"
|
37
37
|
PRICK_PROJECT_PATH = PRICK_PROJECT_FILE
|
38
38
|
|
39
|
-
#
|
40
|
-
|
41
|
-
|
39
|
+
# Environment file
|
40
|
+
PRICK_ENVIRONMENT_FILE = "prick.environment.yml"
|
41
|
+
PRICK_ENVIRONMENT_PATH = PRICK_ENVIRONMENT_FILE
|
42
42
|
|
43
|
-
#
|
44
|
-
|
45
|
-
|
43
|
+
# State file
|
44
|
+
PRICK_STATE_FILE = ".prick.state.yml"
|
45
|
+
PRICK_STATE_PATH = PRICK_STATE_FILE
|
46
46
|
|
47
47
|
# Fox state file (contains anchors and table sizes)
|
48
48
|
FOX_STATE_FILE = ".fox-state.yml"
|
@@ -69,8 +69,8 @@ module Prick
|
|
69
69
|
AFTER_TABLES_DIFF_FILE = "diff.after-tables.sql"
|
70
70
|
]
|
71
71
|
|
72
|
-
|
73
|
-
|
72
|
+
# Default environment
|
73
|
+
DEFAULT_ENVIRONMENT = "default"
|
74
74
|
|
75
75
|
# Not in use:
|
76
76
|
|
data/lib/prick/diff.rb
CHANGED
@@ -34,7 +34,7 @@ module Prick
|
|
34
34
|
file2 = file3 = file1
|
35
35
|
mark = mark.nil? ? true : mark
|
36
36
|
elsif file2.nil? != file3.nil?
|
37
|
-
|
37
|
+
Prick.failure "Either none or both of `file2` and `file3` should be nil"
|
38
38
|
else
|
39
39
|
mark = mark.nil? ? false : mark
|
40
40
|
end
|
@@ -48,7 +48,7 @@ module Prick
|
|
48
48
|
command = "migra --unsafe --with-privileges postgres:///#{@db1} postgres:///#{@db2}"
|
49
49
|
@diff = Command.command(command, fail: false)
|
50
50
|
[0,2].include?(Command.status) or
|
51
|
-
|
51
|
+
Prick.failure "migrate command failed with status #{Command.status}: #{command}"
|
52
52
|
end
|
53
53
|
|
54
54
|
# Initialize table change variables
|
data/lib/prick/environment.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
require 'dsort'
|
3
3
|
|
4
|
+
# TODO:
|
5
|
+
# o Check :parent vs. :inherit (or explain the difference). Also check
|
6
|
+
# handling of :comment
|
7
|
+
|
4
8
|
module Prick
|
9
|
+
# An environment as defined in the prick.environment file. The environment is
|
10
|
+
# constant across all instances of State so we ensure that it is loaded only
|
11
|
+
# once
|
5
12
|
class Environment
|
6
13
|
# Environments name
|
7
14
|
attr_reader :name
|
8
15
|
|
16
|
+
# Environment comment. If not nil, this environment is considered a user-environment
|
17
|
+
attr_accessor :comment
|
18
|
+
|
9
19
|
# Names of parent environments
|
10
20
|
def parents = @values[:parents]
|
11
21
|
|
@@ -18,7 +28,7 @@ module Prick
|
|
18
28
|
def variables = @@VARIABLES
|
19
29
|
|
20
30
|
# List of user defined variables
|
21
|
-
def user_variables = @@VARIABLES - [:
|
31
|
+
def user_variables = @@VARIABLES - [:parents, :comment]
|
22
32
|
|
23
33
|
# Hash from variable to value
|
24
34
|
attr_accessor :values
|
@@ -34,14 +44,15 @@ module Prick
|
|
34
44
|
|
35
45
|
def initialize(name)
|
36
46
|
@name = name
|
47
|
+
@comment = nil
|
37
48
|
@values = variables.map { |key| [key, []] }.to_h
|
38
49
|
@effective_values = variables.map { |key| [key, []] }.to_h
|
39
50
|
@@ENVIRONMENTS[name] = self
|
40
51
|
end
|
41
52
|
|
42
|
-
def self.load_environments(
|
53
|
+
def self.load_environments(yaml) # hash maps from environment name to object
|
43
54
|
if hash
|
44
|
-
parse(
|
55
|
+
parse(yaml)
|
45
56
|
analyze
|
46
57
|
end
|
47
58
|
end
|
@@ -84,18 +95,20 @@ module Prick
|
|
84
95
|
|
85
96
|
def self.parse(hash)
|
86
97
|
hash = hash.dup
|
87
|
-
@@VARIABLES = [:parents] + (yaml_to_array(hash.delete("variables")).map(&:to_sym) || [])
|
98
|
+
@@VARIABLES = [:parents, :comment] + (yaml_to_array(hash.delete("variables") || []).map(&:to_sym) || [])
|
88
99
|
|
89
100
|
for environment, settings in hash
|
90
101
|
env = Environment.new(environment)
|
102
|
+
settings ||= {}
|
91
103
|
if settings.is_a? Hash
|
92
104
|
for variable, value in settings
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
raise ArgumentError, "Illegal variable: '#{variable}'"
|
105
|
+
if variable == "comment"
|
106
|
+
env.comment = value
|
107
|
+
else
|
108
|
+
variable = (variable == "inherit" ? :parents : variable.to_sym)
|
109
|
+
value = yaml_to_array(value)
|
110
|
+
variables.include?(variable) or raise ArgumentError, "Illegal variable: '#{variable}'"
|
111
|
+
env.values[variable] = value
|
99
112
|
end
|
100
113
|
end
|
101
114
|
else
|
data/lib/prick/local/command.rb
CHANGED
@@ -128,8 +128,14 @@ module Command
|
|
128
128
|
STDERR.reopen(pe[1])
|
129
129
|
pe[1].close
|
130
130
|
|
131
|
-
|
132
|
-
|
131
|
+
# Clean bundler environment so that prick can be run in development mode.
|
132
|
+
# The problem is that the bundler environment is inherited by
|
133
|
+
# subprocesses and interferes with loading ruby commands. FIXME This is
|
134
|
+
# only relevant when running prick in development mode
|
135
|
+
ENV.delete_if { |k,v| %w(RUBYOPT RUBYLIB _).include?(k) || k =~ /^BUNDLER?_/ }
|
136
|
+
env = env.map { |k,v| [k.to_s, v.to_s] }.to_h # Convert array values to strings
|
137
|
+
env.each { |k,v| ENV[k] = v }
|
138
|
+
Kernel.exec(env, cmd)
|
133
139
|
}
|
134
140
|
|
135
141
|
pw[0].close
|
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
module Fmt
|
3
|
+
# Print table
|
4
|
+
def self.puts_table(headers, table)
|
5
|
+
widths = headers.map(&:size)
|
6
|
+
signs = []
|
7
|
+
types = []
|
8
|
+
for i in (0...headers.size)
|
9
|
+
widths[i] =
|
10
|
+
(
|
11
|
+
[widths[i]] +
|
12
|
+
table.map { |row|
|
13
|
+
case value = row[i]
|
14
|
+
when TrueClass, FalseClass
|
15
|
+
types[i] = 's'
|
16
|
+
signs[i] = '-'
|
17
|
+
5
|
18
|
+
when NilClass
|
19
|
+
types[i] = 's'
|
20
|
+
signs[i] = '-'
|
21
|
+
4
|
22
|
+
when String
|
23
|
+
types[i] = 's'
|
24
|
+
signs[i] = '-'
|
25
|
+
value.size
|
26
|
+
when Integer
|
27
|
+
types[i] = 'i'
|
28
|
+
signs[i] = ''
|
29
|
+
Math.log10(value) + 1
|
30
|
+
else
|
31
|
+
raise ArgumentError, value
|
32
|
+
end
|
33
|
+
}
|
34
|
+
).max
|
35
|
+
end
|
36
|
+
|
37
|
+
widths = widths.map { _1 }
|
38
|
+
|
39
|
+
for width, value in widths.zip(headers)
|
40
|
+
printf "%-#{width}s ", value
|
41
|
+
end
|
42
|
+
puts
|
43
|
+
widths.each.with_index { |width, index|
|
44
|
+
char = (headers[index] =~ /^\s*$/ ? " " : "-")
|
45
|
+
printf "%#{width}s ", char * width
|
46
|
+
}
|
47
|
+
puts
|
48
|
+
for row in table
|
49
|
+
for sign, width, type, value in signs.zip(widths, types, row)
|
50
|
+
value = (value.nil? ? "-" : value)
|
51
|
+
printf "%#{sign}#{width}#{type} ", value
|
52
|
+
end
|
53
|
+
puts
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/prick/prick_version.rb
CHANGED
@@ -77,7 +77,7 @@ module Prick
|
|
77
77
|
@semver = version.semver.dup
|
78
78
|
@feature = feature || version.feature
|
79
79
|
else
|
80
|
-
raise
|
80
|
+
raise ArgumentError, "Expected a String, PrickVersion, or Semantic::Version, got #{version.class}"
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -1,5 +1,14 @@
|
|
1
|
+
# Controlled by the prick command. Don't change
|
2
|
+
#
|
3
|
+
# Note the SQL scripts are also called directly from 'prick setup' when the
|
4
|
+
# database is created because we don't want to parse the whole build
|
5
|
+
# environment just to create the prick schema. After the initial setup, the
|
6
|
+
# scripts are only run by 'prick build' with the --force option
|
7
|
+
#
|
8
|
+
# This is hardcoded an should be fixed somehow
|
9
|
+
#
|
1
10
|
---
|
2
11
|
- schema: prick
|
12
|
+
refresh: false # Because the build process takes care of this
|
3
13
|
- tables.sql
|
4
|
-
-
|
5
|
-
- data.sql
|
14
|
+
- views.sql
|
@@ -1,16 +1,37 @@
|
|
1
1
|
-- Controlled by prick(1). Don't touch
|
2
2
|
--
|
3
|
+
-- TODO
|
4
|
+
-- o Replace view with a function to return the current build
|
3
5
|
|
4
6
|
set search_path to prick;
|
5
7
|
|
6
|
-
create table
|
8
|
+
create table builds (
|
7
9
|
id integer generated by default as identity primary key,
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
|
11
|
+
-- Project name
|
12
|
+
name varchar not null,
|
13
|
+
|
14
|
+
-- Version
|
15
|
+
version varchar not null, -- Project version
|
16
|
+
prick varchar not null,-- Prick version
|
17
|
+
|
18
|
+
-- Git
|
19
|
+
branch varchar not null,
|
20
|
+
rev varchar not null, -- commit ID
|
21
|
+
clean boolean not null default true, -- True if git repository is clean
|
22
|
+
|
23
|
+
-- Environment
|
24
|
+
environment varchar not null default 'default',
|
25
|
+
|
26
|
+
-- Build timestamp. This is the time of the start of the build
|
27
|
+
built_at timestamp without time zone default (now() at time zone 'UTC'),
|
28
|
+
|
29
|
+
-- Build status
|
30
|
+
success boolean default false,-- True if the database built successfully
|
31
|
+
|
32
|
+
-- Durations
|
33
|
+
duration float,-- Duration of database build. Null if success is false
|
34
|
+
prick_duration float, -- Duration of the full prick command
|
35
|
+
make_duration float -- Duration of enclosing make script
|
16
36
|
);
|
37
|
+
|