Module: Prick

Defined in:
lib/prick/environment.rb,
lib/prick.rb,
lib/prick/diff.rb,
lib/prick/state.rb,
lib/prick-command.rb,
lib/prick-command.rb,
lib/prick-command.rb,
lib/prick/version.rb,
lib/prick/constants.rb,
lib/prick/local/git.rb,
lib/prick/builder/node.rb,
lib/prick/builder/batch.rb,
lib/prick/prick_version.rb,
lib/prick/builder/parser.rb,
lib/prick/builder/builder.rb,
lib/prick/builder/node_pool.rb,
lib/prick/subcommand/prick-create.rb,
lib/prick/subcommand/prick-migrate.rb,
lib/prick/subcommand/prick-release.rb

Overview

Project related code starts here

Defined Under Namespace

Modules: Build, Git, SubCommand Classes: Diff, Environment, Environments, Error, Failure, PrickVersion, State

Constant Summary collapse

VERSION =
"0.40.2"
EPOCH =

TIME

Time.at(0).utc
SHARE_PATH =

Shared files (part of the installation)

"#{File.dirname(File.dirname(__dir__))}/lib/prick/share"
LIBEXEC_PATH =
"#{File.dirname(File.dirname(__dir__))}/lib/prick/libexec"
DIRS =

Project directories

[
  MIGRATION_DIR = "migration",
  SCHEMA_DIR = "schema",
  SCHEMA_PRICK_DIR = "#{SCHEMA_DIR}/prick",
  PUBLIC_DIR = "#{SCHEMA_DIR}/public",
  BIN_DIR = "bin",
  LIBEXEC_DIR = "libexec",
  VAR_DIR = "var",
  CACHE_DIR = "#{VAR_DIR}/cache",
  SPOOL_DIR = "#{VAR_DIR}/spool",
  TMP_DIR = "tmp",
  CLONE_DIR = "tmp/clones",
  SPEC_DIR = "spec"
]
PRICK_DIR =

Prick project root directory

Dir.getwd
PRICK_PROJECT_FILE =

Project file

"prick.yml"
PRICK_PROJECT_PATH =
PRICK_PROJECT_FILE
PRICK_ENVIRONMENT_FILE =

Environment file

"prick.environment.yml"
PRICK_ENVIRONMENT_PATH =
PRICK_ENVIRONMENT_FILE
PRICK_STATE_FILE =

State file

".prick.state.yml"
PRICK_STATE_PATH =
PRICK_STATE_FILE
FOX_STATE_FILE =

Fox state file (contains anchors and table sizes)

".fox-state.yml"
FOX_STATE_PATH =
FOX_STATE_FILE
PG_META_STATE_FILE =

PgMeta snapshot. Is deleted at the start of each build

".pg_meta-state.yml"
PG_META_STATE_PATH =
PG_META_STATE_FILE
REFLECTIONS_FILE =

Reflections file

"reflections.yml"
REFLECTIONS_PATH =
File.join(SCHEMA_DIR, REFLECTIONS_FILE)
SCHEMA_VERSION_FILE =

Schema data file

"data.sql"
SCHEMA_VERSION_PATH =
File.join(SCHEMA_PRICK_DIR, SCHEMA_VERSION_FILE)
SPEC_TMP_DIR =

Rspec temporary directory

"spec"
SPEC_TMP_PATH =
File.join(TMP_DIR, SPEC_TMP_DIR)
DIFF_FILE =

Migration diff files

"diff.sql"
DIFF_FILES =
[
  BEFORE_TABLES_DIFF_FILE = "diff.before-tables.sql",
  TABLES_DIFF_FILE = "diff.tables.sql",
  AFTER_TABLES_DIFF_FILE = "diff.after-tables.sql"
]
DEFAULT_ENVIRONMENT =

Default environment

"default"
PROJECT_STATE_FILE =

The project state file

".prick-project"
PROJECT_STATE_PATH =
PROJECT_STATE_FILE
PRICK_MIGRATION_FILE =

The the .prick-migration file

".prick-migration"
PRICK_MIGRATION_PATH =
File.join(MIGRATION_DIR, PRICK_MIGRATION_FILE)
PRICK_FEATURE_FILE =

The the .prick-feature file

".prick-feature"
PRICK_FEATURE_PATH =
File.join(MIGRATION_DIR, PRICK_FEATURE_FILE)
STRIP_COMMENTS_NAME =

The strip-comments executable

"strip-comments"
STRIP_COMMENTS_PATH =
File.join(LIBEXEC_PATH, "strip-comments")
DUMP_EXT =

Dump files

"dump.gz"
DUMP_GLOB =
"*-[0-9]*.#{DUMP_EXT}"
NAME_SUB_RE =

Matches a system name. System names are used for objects that are external to prick (like usernames)

/[a-z][a-z0-9_-]*/
NAME_RE =
/^#{NAME_SUB_RE}$/
IDENT_SUB_RE =

Matches an identifier. Identifiers consist of lower case letters, digits and underscores but not dashes because they’re used as separators

/[a-z][a-z0-9_]*/
IDENT_RE =
/^#{IDENT_SUB_RE}$/
PROJECT_NAME_SUB_RE =

Matches a project name

IDENT_SUB_RE
PROJECT_NAME_RE =
IDENT_RE
CUSTOM_NAME_SUB_RE =

Matches a custom name

IDENT_SUB_RE
CUSTOM_NAME_RE =
IDENT_RE
FEATURE_NAME_SUB_RE =

Matches a feature name

/(?!initial)#{IDENT_SUB_RE}/
FEATURE_NAME_RE =
/^#{FEATURE_NAME_SUB_RE}$/
USER_NAME_SUB_RE =

Matches a postgres user name

NAME_SUB_RE
USER_NAME_RE =
NAME_RE
MMP_SEMVER_SUB_RE =

Matches a major.minor.patch (‘MMP’) version

The *_SEMVER REs are derived from the canonical RE

/

(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)
(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?
(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?

/x

semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string.

/(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)/
MMP_SEMVER_RE =
/^#{MMP_SEMVER_SUB_RE}$/
PRE_SEMVER_SUB_RE =

Matches the prelease part of a semantic version

/pre\.\d+/
PRE_SEMVER_RE =
/^#{PRE_SEMVER_SUB_RE}$/
SEMVER_SUB_RE =

Matches a semantic version

/#{MMP_SEMVER_SUB_RE}(?:-#{PRE_SEMVER_SUB_RE})?/
SEMVER_RE =
/^#{SEMVER_SUB_RE}$/
TAG_SUB_RE =

Tag RE. The general syntax for a tag is ‘<custom>-v<version>_<feature>’

The RE defines the following captures:

$1 - custom name, can be nil
$2 - semantic version
$3 - feature name, can be nil
/
    (?:(#{CUSTOM_NAME_SUB_RE})-)?
    v
    (#{SEMVER_SUB_RE})
    (?:_(#{FEATURE_NAME_SUB_RE}))?
/x
TAG_RE =
/^#{TAG_SUB_RE}$/
BRANCH_SUB_RE =

Branch RE. The general syntax for a branch is ‘<custom>-<version>_<feature>’

The RE defines the following captures:

$1 - custom name, can be nil
$2 - semantic version
$3 - feature name, can be nil
/
    (?:(#{CUSTOM_NAME_SUB_RE})-)?
    (#{SEMVER_SUB_RE})
    (?:_(#{FEATURE_NAME_SUB_RE}))?
/x
BRANCH_RE =
/^#{BRANCH_SUB_RE}$/
VERSION_SUB_RE =

Tag or branch RE. The general syntax for a branch is ‘<custom>-v?<version>_<feature>’

The RE defines the following captures:

$1 - custom name, can be nil
$2 - tag, nil or 'v'
$3 - semantic version
$4 - feature name, can be nil
/
    (?:(#{CUSTOM_NAME_SUB_RE})-)?
    (v)?
    (#{SEMVER_SUB_RE})
    (?:_(#{FEATURE_NAME_SUB_RE}))?
/x
VERSION_RE =
/^#{VERSION_SUB_RE}$/
ABSTRACT_RELEASE_SUB_RE =

Matches an abstract release (either a release or a prerelease)

The RE defines the following captures:

$1 - custom name, can be nil
$2 - semantic version
/
    (?:(#{CUSTOM_NAME_SUB_RE})-)?
    (#{SEMVER_SUB_RE})
/x
ABSTRACT_RELEASE_RE =
/^#{ABSTRACT_RELEASE_SUB_RE}$/
PROJECT_SUB_RE =

Project release RE. The general syntax is ‘<project>-<custom>-<version>’

The RE defines the following captures:

$1 - project
$2 - version
$3 - custom name, can be nil
$4 - semantic version
/(#{PROJECT_NAME_SUB_RE})-(#{ABSTRACT_RELEASE_SUB_RE})/
PROJECT_RE =
/^#{PROJECT_SUB_RE}$/
DATABASE_SUB_RE =

Matches versioned databases. Note that databases never include the feature name. Features use the project database instead of a feature-specific database

The RE defines the following captures

$1 - project
$2 - version
$3 - custom name, can be nil
$4 - semantic version
PROJECT_SUB_RE
DATABASE_RE =
/^#{DATABASE_SUB_RE}$/
ALL_DATABASES_SUB_RE =

Matches project database and versioned databases

The RE defines the following captures

$1 - project
$2 - version, can be nil
$3 - custom name, can be nil
$4 - semantic version, can be nil
/(#{PROJECT_NAME_SUB_RE})(?:-(#{ABSTRACT_RELEASE_SUB_RE}))?/
ALL_DATABASES_RE =
/^#{ALL_DATABASES_SUB_RE}$/
TMP_DATABASES_SUB_RE =

Matches temporary databases. Mostly useful when debugging because temporary databases should be deleted on exit

/#{PROJECT_NAME_SUB_RE}-(?:base|next)/
TMP_DATABASES_RE =
/^#{TMP_DATABASES_SUB_RE}$/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.all_databases_re(project_name) ⇒ Object



269
# File 'lib/prick/constants.rb', line 269

def self.all_databases_re(project_name) /^#{all_databases_sub_re(project_name)}$/ end

.all_databases_sub_re(project_name) ⇒ Object



268
# File 'lib/prick/constants.rb', line 268

def self.all_databases_sub_re(project_name) /(#{project_name})(?:-(#{ABSTRACT_RELEASE_SUB_RE}))?/ end

.call(ruby_script) ⇒ Object

Call a ruby script using fork. This is much faster than calling the script using #system and it shares the database connection with the current process

The script is supposed to require ‘prick.rb’ to get access to the Prick.conn function that returns the current database when run in a Prick environment

require 'prick.rb'
conn = Prick.conn database, username


107
108
109
110
111
112
113
114
115
116
# File 'lib/prick-command.rb', line 107

def self.call(ruby_script)
  File.exist?(ruby_script) or raise ArgumentError, "Can't find script '#{ruby_script}' in Prick.call"

  pid = fork do
    require(File.join(Dir.getwd, ruby_script))
  end
  Process.wait(pid)
  $?.exitstatus == 0 or raise ArgumentError, "Ruby script '#{ruby_script}' failed"
  owner_conn.reset
end

.conn(database, username) ⇒ Object



5
6
7
8
9
10
11
# File 'lib/prick.rb', line 5

def self.conn(database, username)
  if self.respond_to?(:owner_conn)
    self.owner_conn
  else
    PgConn.new(database, username)
  end
end

.database_re(project_name) ⇒ Object



256
# File 'lib/prick/constants.rb', line 256

def self.database_re(project_name) /^#{database_sub_re(project_name)}$/ end

.database_sub_re(project_name) ⇒ Object



255
# File 'lib/prick/constants.rb', line 255

def self.database_sub_re(project_name) project_sub_re(project_name) end

.databases(&block) ⇒ Object

Return list of prick databases. If a block is given it is called with a connection to each of the databases



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/prick-command.rb', line 76

def self.databases(&block)
  databases = super_conn.values %(
    select datname from pg_database where datistemplate = false order by datname
  )
  databases.select! { |database|
    PgConn.new(database) { |conn|
      is_prick_database = conn.exist?(%(
          select 1
          from information_schema.tables
          where table_schema = 'prick'
          and table_name = 'builds'
          limit 1
      ))
      yield(database, conn) if is_prick_database && block_given?
      is_prick_database
    }
  }
  databases
end

.dump_glob(project_name) ⇒ Object



115
# File 'lib/prick/constants.rb', line 115

def self.dump_glob(project_name) "#{project_name}-*.#{DUMP_EXT}" end

.error(*args) ⇒ Object



67
# File 'lib/prick-command.rb', line 67

def self.error(*args) raise Prick::Error.new *args end

.failure(*args) ⇒ Object



68
# File 'lib/prick-command.rb', line 68

def self.failure(*args) raise Prick::Failure.new *args end

.mesg(*msgs) ⇒ Object



38
# File 'lib/prick-command.rb', line 38

def self.mesg(*msgs) puts msgs.join(" ") if !$quiet end

.owner_connObject



70
# File 'lib/prick-command.rb', line 70

def self.owner_conn = state.connection

.project_sub_re(project_name) ⇒ Object



239
240
241
# File 'lib/prick/constants.rb', line 239

def self.project_sub_re(project_name)
  /(#{Regexp.escape(project_name)})(-#{VERSION_SUB_RE})/
end

.release_re(project_name) ⇒ Object



242
# File 'lib/prick/constants.rb', line 242

def self.release_re(project_name) /^#{project_sub_re(project_name)}$/ end

.stateObject



64
# File 'lib/prick-command.rb', line 64

def self.state() @state or raise ArgumentError end

.state=(state) ⇒ Object



65
# File 'lib/prick-command.rb', line 65

def self.state=(state) @state = state end

.state?Boolean

Returns:

  • (Boolean)


63
# File 'lib/prick-command.rb', line 63

def self.state?() !@state.nil? end

.super_connObject



71
72
# File 'lib/prick-command.rb', line 71

def self.super_conn = State.connection
# def self.conn = owner_conn

.tmp_databases_re(project_name) ⇒ Object



276
# File 'lib/prick/constants.rb', line 276

def self.tmp_databases_re(project_name) /^#{tmp_databases_sub_re(project_name)}$/ end

.tmp_databases_sub_re(project_name) ⇒ Object



275
# File 'lib/prick/constants.rb', line 275

def self.tmp_databases_sub_re(project_name) /#{project_name}-(?:base|next)/ end

.verb(*msgs) ⇒ Object



39
# File 'lib/prick-command.rb', line 39

def self.verb(*msgs) puts msgs.join(" ") if $verbose && !$quiet end

Instance Method Details

#mesg(*msgs) ⇒ Object



36
# File 'lib/prick-command.rb', line 36

def mesg(*msgs) = Prick.mesg(*msgs)

#verb(*msgs) ⇒ Object



37
# File 'lib/prick-command.rb', line 37

def verb(*msgs) = Prick.verb(*msgs)