code0-zero_track 0.0.0 → 0.0.1
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 +4 -4
- data/LICENSE +0 -0
- data/README.md +48 -0
- data/Rakefile +0 -0
- data/lib/code0/zero_track/context.rb +133 -0
- data/lib/code0/zero_track/database/column_methods.rb +35 -0
- data/lib/code0/zero_track/database/migration.rb +26 -0
- data/lib/code0/zero_track/database/migration_helpers/add_column_enhancements.rb +41 -0
- data/lib/code0/zero_track/database/migration_helpers/constraint_helpers.rb +22 -0
- data/lib/code0/zero_track/database/migration_helpers/index_helpers.rb +18 -0
- data/lib/code0/zero_track/database/migration_helpers/table_enhancements.rb +78 -0
- data/lib/code0/zero_track/database/postgresql_adapter/dump_schema_versions_mixin.rb +27 -0
- data/lib/code0/zero_track/database/postgresql_database_tasks/load_schema_versions_mixin.rb +26 -0
- data/lib/code0/zero_track/database/schema_cleaner.rb +51 -0
- data/lib/code0/zero_track/database/schema_migrations/context.rb +48 -0
- data/lib/code0/zero_track/database/schema_migrations/migrations.rb +62 -0
- data/lib/code0/zero_track/database/schema_migrations.rb +32 -0
- data/lib/code0/zero_track/injectors/active_record_schema_migrations.rb +20 -0
- data/lib/code0/zero_track/injectors/active_record_timestamps.rb +21 -0
- data/lib/code0/zero_track/loggable.rb +48 -0
- data/lib/code0/zero_track/logs/json_formatter.rb +42 -0
- data/lib/code0/zero_track/memoize.rb +50 -0
- data/lib/code0/zero_track/railtie.rb +15 -0
- data/lib/code0/zero_track/version.rb +1 -1
- data/lib/code0/zero_track.rb +10 -2
- data/lib/tasks/code0/zero_track_tasks.rake +33 -4
- metadata +53 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 528e1dc7d30d7cc16b1507b9649429a03196747fe18b27086c23cbdfe9b85147
|
4
|
+
data.tar.gz: ff9eae6c20639f631b0fce5b3de912a73d76bb1f0e77a7e16b32fac2d645cbbc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ee327ee87f60a1d8865d6abb3b1dc322a28bdc57b7a6d31f06a7d1af17425ed8e7d6af4178417d8db5ad9e84cd6794ae4a2612c1ebd65dfb4968f7b3d1e1e35
|
7
|
+
data.tar.gz: eb42c512f19919608444053fb33be11229e7968a1e6bb231b82ec9415d528baabe83051d41ba5a0335afbc0a2ec6b428c4dd420c29a03d4afcf812667b34cad0
|
data/LICENSE
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -18,3 +18,51 @@ Or install it yourself as:
|
|
18
18
|
```bash
|
19
19
|
$ gem install code0-zero_track
|
20
20
|
```
|
21
|
+
|
22
|
+
## Features
|
23
|
+
|
24
|
+
### `Code0::ZeroTrack::Context`
|
25
|
+
|
26
|
+
Context allows you to save data in a thread local object. Data from the Context is merged into the
|
27
|
+
log messages, if `Code0::ZeroTrack::Logs::JsonFormatter` or `Code0::ZeroTrack::Logs::JsonFormatter::Tagged`
|
28
|
+
is used.
|
29
|
+
|
30
|
+
`.with_context(data, &block)` creates a new context inheriting data from the previous context and adds the
|
31
|
+
passed data to it. The new context is dropped after the block finished execution. \
|
32
|
+
`.push(data)` creates a new context inheriting data from the previous context and adds the passed data to it. \
|
33
|
+
`.current` returns the context from the top of the stack.
|
34
|
+
|
35
|
+
### `Code0::ZeroTrack::Memoize`
|
36
|
+
|
37
|
+
This module can be included to get access to the `memoize(name, reset_on_change, &block)` method.
|
38
|
+
|
39
|
+
This method allows to memoize a value, so it only gets computed once.
|
40
|
+
Each memoize is identified by the name. You can pass a proc to `reset_on_change` and the memoization
|
41
|
+
will automatically clear every time returned value changes.
|
42
|
+
|
43
|
+
`memoized?(name)` allows to check if a value for the given name is currently memoized. \
|
44
|
+
Memoizations can be cleared with `clear_memoize(name)` or `clear_memoize!(name)`.
|
45
|
+
|
46
|
+
### `config.zero_track.active_record.schema_cleaner`
|
47
|
+
|
48
|
+
When using `config.active_record.schema_format = :sql`, Rails produces a `db/structure.sql`.
|
49
|
+
This file contains a lot of noise that doesn't provide much value.
|
50
|
+
|
51
|
+
This noise can be cleaned out with `config.zero_track.active_record.schema_cleaner = true`.
|
52
|
+
|
53
|
+
### `config.zero_track.active_record.timestamps`
|
54
|
+
|
55
|
+
Setting `config.zero_track.active_record.timestamps = true` adds `timestamps_with_timezone`
|
56
|
+
and `datetime_with_timezone` as methods on the table model when creating tables in migrations.
|
57
|
+
|
58
|
+
They behave just like `timestamps` and `datetime`, just including timezones.
|
59
|
+
|
60
|
+
### `config.zero_track.active_record.schema_migrations`
|
61
|
+
|
62
|
+
Rails uses the `schema_migrations` table to keep track which migrations have been executed.
|
63
|
+
This information is also persisted in the `db/structure.sql`, so the `schema_migrations` table
|
64
|
+
can be filled with the correct entries when the schema is loaded from the schema file.
|
65
|
+
|
66
|
+
This approach is prone to git conflicts, so you can switch to a file based persistence
|
67
|
+
with `config.zero_track.active_record.schema_migrations = true`. Instead of an `INSERT INTO` in
|
68
|
+
the `db/structure.sql`, this mode creates files in the `db/schema_migrations` directory.
|
data/Rakefile
CHANGED
File without changes
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
class Context
|
6
|
+
LOG_KEY = 'meta'
|
7
|
+
CORRELATION_ID_KEY = 'correlation_id'
|
8
|
+
RAW_KEYS = [CORRELATION_ID_KEY].freeze
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def with_context(attributes = {})
|
12
|
+
context = push(attributes)
|
13
|
+
|
14
|
+
begin
|
15
|
+
yield(context)
|
16
|
+
ensure
|
17
|
+
pop(context)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def push(new_attributes = {})
|
22
|
+
new_context = current&.merge(new_attributes) || new(new_attributes)
|
23
|
+
|
24
|
+
contexts.push(new_context)
|
25
|
+
|
26
|
+
new_context
|
27
|
+
end
|
28
|
+
|
29
|
+
def pop(context)
|
30
|
+
contexts.pop while contexts.include?(context)
|
31
|
+
end
|
32
|
+
|
33
|
+
def correlation_id
|
34
|
+
current&.correlation_id
|
35
|
+
end
|
36
|
+
|
37
|
+
def current
|
38
|
+
contexts.last
|
39
|
+
end
|
40
|
+
|
41
|
+
def log_key(key)
|
42
|
+
key = key.to_s
|
43
|
+
return key if RAW_KEYS.include?(key)
|
44
|
+
return key if key.start_with?("#{LOG_KEY}.")
|
45
|
+
|
46
|
+
"#{LOG_KEY}.#{key}"
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def contexts
|
52
|
+
Thread.current[:labkit_contexts] ||= []
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(values = {})
|
57
|
+
@data = {}
|
58
|
+
|
59
|
+
assign_attributes(values)
|
60
|
+
end
|
61
|
+
|
62
|
+
def merge(new_attributes)
|
63
|
+
new_context = self.class.new(data.dup)
|
64
|
+
new_context.assign_attributes(new_attributes)
|
65
|
+
|
66
|
+
new_context
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_h
|
70
|
+
expand_data
|
71
|
+
end
|
72
|
+
|
73
|
+
def [](key)
|
74
|
+
to_h[log_key(key)]
|
75
|
+
end
|
76
|
+
|
77
|
+
def correlation_id
|
78
|
+
data[CORRELATION_ID_KEY]
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_attribute(attribute)
|
82
|
+
raw = call_or_value(data[log_key(attribute)])
|
83
|
+
|
84
|
+
call_or_value(raw)
|
85
|
+
end
|
86
|
+
|
87
|
+
protected
|
88
|
+
|
89
|
+
def assign_attributes(attributes)
|
90
|
+
attributes = attributes.transform_keys(&method(:log_key))
|
91
|
+
|
92
|
+
data.merge!(attributes)
|
93
|
+
|
94
|
+
# Remove keys that had their values set to `nil` in the new attributes
|
95
|
+
data.keep_if { |_, value| valid_data?(value) }
|
96
|
+
|
97
|
+
# Assign a correlation if it was missing in the first context or when
|
98
|
+
# explicitly removed
|
99
|
+
data[CORRELATION_ID_KEY] ||= new_id
|
100
|
+
|
101
|
+
data
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
attr_reader :data
|
107
|
+
|
108
|
+
def log_key(key)
|
109
|
+
self.class.log_key(key)
|
110
|
+
end
|
111
|
+
|
112
|
+
def call_or_value(value)
|
113
|
+
value.respond_to?(:call) ? value.call : value
|
114
|
+
end
|
115
|
+
|
116
|
+
def expand_data
|
117
|
+
data.transform_values do |value|
|
118
|
+
value = call_or_value(value)
|
119
|
+
|
120
|
+
value if valid_data?(value)
|
121
|
+
end.compact
|
122
|
+
end
|
123
|
+
|
124
|
+
def new_id
|
125
|
+
SecureRandom.hex
|
126
|
+
end
|
127
|
+
|
128
|
+
def valid_data?(value)
|
129
|
+
value == false || value.present?
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Database
|
6
|
+
module ColumnMethods
|
7
|
+
module Timestamps
|
8
|
+
# Appends columns `created_at` and `updated_at` to a table.
|
9
|
+
#
|
10
|
+
# It is used in table creation like:
|
11
|
+
# create_table 'users' do |t|
|
12
|
+
# t.timestamps_with_timezone
|
13
|
+
# end
|
14
|
+
def timestamps_with_timezone(**options)
|
15
|
+
options[:null] = false if options[:null].nil?
|
16
|
+
|
17
|
+
%i[created_at updated_at].each do |column_name|
|
18
|
+
column(column_name, :datetime_with_timezone, **options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Adds specified column with appropriate timestamp type
|
23
|
+
#
|
24
|
+
# It is used in table creation like:
|
25
|
+
# create_table 'users' do |t|
|
26
|
+
# t.datetime_with_timezone :did_something_at
|
27
|
+
# end
|
28
|
+
def datetime_with_timezone(column_name, **options)
|
29
|
+
column(column_name, :datetime_with_timezone, **options)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Database
|
6
|
+
class Migration
|
7
|
+
# rubocop:disable Naming/ClassAndModuleCamelCase
|
8
|
+
class V1_0 < ::ActiveRecord::Migration[7.1]
|
9
|
+
include Database::MigrationHelpers::AddColumnEnhancements
|
10
|
+
include Database::MigrationHelpers::ConstraintHelpers
|
11
|
+
include Database::MigrationHelpers::IndexHelpers
|
12
|
+
include Database::MigrationHelpers::TableEnhancements
|
13
|
+
end
|
14
|
+
# rubocop:enable Naming/ClassAndModuleCamelCase
|
15
|
+
|
16
|
+
def self.[](version)
|
17
|
+
version = version.to_s
|
18
|
+
name = "V#{version.tr('.', '_')}"
|
19
|
+
raise ArgumentError, "Invalid migration version: #{version}" unless const_defined?(name, false)
|
20
|
+
|
21
|
+
const_get(name, false)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Database
|
6
|
+
module MigrationHelpers
|
7
|
+
module AddColumnEnhancements
|
8
|
+
def add_column(table_name, column_name, type, *args, **kwargs, &block)
|
9
|
+
helper_context = self
|
10
|
+
|
11
|
+
limit = kwargs.delete(:limit)
|
12
|
+
unique = kwargs.delete(:unique)
|
13
|
+
|
14
|
+
super
|
15
|
+
|
16
|
+
return unless type == :text
|
17
|
+
|
18
|
+
quoted_column_name = helper_context.quote_column_name(column_name)
|
19
|
+
|
20
|
+
if limit
|
21
|
+
name = helper_context.send(:text_limit_name, table_name, column_name)
|
22
|
+
|
23
|
+
definition = "char_length(#{quoted_column_name}) <= #{limit}"
|
24
|
+
|
25
|
+
add_check_constraint(table_name, definition, name: name)
|
26
|
+
end
|
27
|
+
|
28
|
+
if unique.is_a?(Hash)
|
29
|
+
unique[:where] = "#{column_name} IS NOT NULL" if unique.delete(:allow_nil_duplicate)
|
30
|
+
column_name = "LOWER(#{quoted_column_name})" if unique.delete(:case_insensitive)
|
31
|
+
|
32
|
+
add_index table_name, column_name, unique: true, **unique
|
33
|
+
elsif unique
|
34
|
+
add_index table_name, column_name, unique: unique
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Database
|
6
|
+
module MigrationHelpers
|
7
|
+
module ConstraintHelpers
|
8
|
+
def text_limit_name(table, column, name: nil)
|
9
|
+
name.presence || check_constraint_name(table, column, 'max_length')
|
10
|
+
end
|
11
|
+
|
12
|
+
def check_constraint_name(table, column, type)
|
13
|
+
identifier = "#{table}_#{column}_check_#{type}"
|
14
|
+
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
|
15
|
+
|
16
|
+
"check_#{hashed_identifier}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Database
|
6
|
+
module MigrationHelpers
|
7
|
+
module IndexHelpers
|
8
|
+
def index_name(table, column, type)
|
9
|
+
identifier = "#{table}_#{column}_index_#{type}"
|
10
|
+
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
|
11
|
+
|
12
|
+
"index_#{hashed_identifier}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Database
|
6
|
+
module MigrationHelpers
|
7
|
+
module TableEnhancements
|
8
|
+
def create_table(table_name, *args, **kwargs, &block)
|
9
|
+
helper_context = self
|
10
|
+
|
11
|
+
super do |t|
|
12
|
+
enhance(t, table_name, helper_context, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def change_table(table_name, *args, **kwargs, &block)
|
17
|
+
helper_context = self
|
18
|
+
|
19
|
+
super do |t|
|
20
|
+
enhance(t, table_name, helper_context, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def enhance(t, table_name, helper_context, &block)
|
27
|
+
t.define_singleton_method(:text) do |column_name, **inner_kwargs|
|
28
|
+
limit = inner_kwargs.delete(:limit)
|
29
|
+
unique = inner_kwargs.delete(:unique)
|
30
|
+
|
31
|
+
super(column_name, **inner_kwargs)
|
32
|
+
|
33
|
+
quoted_column_name = helper_context.quote_column_name(column_name)
|
34
|
+
|
35
|
+
if limit
|
36
|
+
name = helper_context.send(:text_limit_name, table_name, column_name)
|
37
|
+
|
38
|
+
definition = "char_length(#{quoted_column_name}) <= #{limit}"
|
39
|
+
|
40
|
+
t.check_constraint(definition, name: name)
|
41
|
+
end
|
42
|
+
|
43
|
+
if unique.is_a?(Hash)
|
44
|
+
index_definition = column_name
|
45
|
+
unique[:where] = "#{column_name} IS NOT NULL" if unique.delete(:allow_nil_duplicate)
|
46
|
+
index_definition = "LOWER(#{quoted_column_name})" if unique.delete(:case_insensitive)
|
47
|
+
|
48
|
+
t.index index_definition, unique: true, **unique
|
49
|
+
elsif unique
|
50
|
+
t.index column_name, unique: unique
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
t.define_singleton_method(:integer) do |column_name, **inner_kwargs|
|
55
|
+
unique = inner_kwargs.delete(:unique)
|
56
|
+
|
57
|
+
super(column_name, **inner_kwargs)
|
58
|
+
|
59
|
+
t.index column_name, unique: unique unless unique.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
return if block.nil?
|
63
|
+
|
64
|
+
t.instance_eval do |obj|
|
65
|
+
if block.arity == 1
|
66
|
+
block.call(obj)
|
67
|
+
elsif block.arity == 2
|
68
|
+
block.call(obj, helper_context)
|
69
|
+
else
|
70
|
+
raise ArgumentError, "Unsupported arity of #{block.arity}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Heavily inspired by the implementation of GitLab
|
4
|
+
# (https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/lib/gitlab/database/postgresql_adapter/dump_schema_versions_mixin.rb)
|
5
|
+
# which is licensed under a modified version of the MIT license which can be found at
|
6
|
+
# https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/LICENSE
|
7
|
+
#
|
8
|
+
# The code might have been modified to accommodate for the needs of this project
|
9
|
+
|
10
|
+
module Code0
|
11
|
+
module ZeroTrack
|
12
|
+
module Database
|
13
|
+
module PostgresqlAdapter
|
14
|
+
module DumpSchemaVersionsMixin
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
|
17
|
+
def dump_schema_information
|
18
|
+
# rubocop:disable Rails/SkipsModelValidations -- not an active record object
|
19
|
+
Database::SchemaMigrations.touch_all(self) unless Rails.env.production?
|
20
|
+
# rubocop:enable Rails/SkipsModelValidations
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Heavily inspired by the implementation of GitLab
|
4
|
+
# (https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/lib/gitlab/database/postgresql_database_tasks/load_schema_versions_mixin.rb)
|
5
|
+
# which is licensed under a modified version of the MIT license which can be found at
|
6
|
+
# https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/LICENSE
|
7
|
+
#
|
8
|
+
# The code might have been modified to accommodate for the needs of this project
|
9
|
+
|
10
|
+
module Code0
|
11
|
+
module ZeroTrack
|
12
|
+
module Database
|
13
|
+
module PostgresqlDatabaseTasks
|
14
|
+
module LoadSchemaVersionsMixin
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
|
17
|
+
def structure_load(...)
|
18
|
+
super
|
19
|
+
|
20
|
+
Database::SchemaMigrations.load_all(connection)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Heavily inspired by the implementation of GitLab
|
4
|
+
# (https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/lib/gitlab/database/schema_cleaner.rb)
|
5
|
+
# which is licensed under a modified version of the MIT license which can be found at
|
6
|
+
# https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/LICENSE
|
7
|
+
#
|
8
|
+
# The code might have been modified to accommodate for the needs of this project
|
9
|
+
|
10
|
+
module Code0
|
11
|
+
module ZeroTrack
|
12
|
+
module Database
|
13
|
+
class SchemaCleaner
|
14
|
+
attr_reader :original_schema
|
15
|
+
|
16
|
+
def initialize(original_schema)
|
17
|
+
@original_schema = original_schema
|
18
|
+
end
|
19
|
+
|
20
|
+
def clean(io)
|
21
|
+
structure = original_schema.dup
|
22
|
+
|
23
|
+
# Remove noise
|
24
|
+
structure.gsub!(/^COMMENT ON EXTENSION.*/, '')
|
25
|
+
structure.gsub!(/^SET.+/, '')
|
26
|
+
structure.gsub!(/^SELECT pg_catalog\.set_config\('search_path'.+/, '')
|
27
|
+
structure.gsub!(/^--.*/, "\n")
|
28
|
+
|
29
|
+
# We typically don't assume we're working with the public schema.
|
30
|
+
# pg_dump uses fully qualified object names though, since we have multiple schemas
|
31
|
+
# in the database.
|
32
|
+
#
|
33
|
+
# The intention here is to not introduce an assumption about the standard schema,
|
34
|
+
# unless we have a good reason to do so.
|
35
|
+
structure.gsub!(/public\.(\w+)/, '\1')
|
36
|
+
structure.gsub!(
|
37
|
+
/CREATE EXTENSION IF NOT EXISTS (\w+) WITH SCHEMA public;/,
|
38
|
+
'CREATE EXTENSION IF NOT EXISTS \1;'
|
39
|
+
)
|
40
|
+
|
41
|
+
structure.gsub!(/\n{3,}/, "\n\n")
|
42
|
+
|
43
|
+
io << structure.strip
|
44
|
+
io << "\n"
|
45
|
+
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Heavily inspired by the implementation of GitLab
|
4
|
+
# (https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/lib/gitlab/database/schema_migrations/context.rb)
|
5
|
+
# which is licensed under a modified version of the MIT license which can be found at
|
6
|
+
# https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/LICENSE
|
7
|
+
#
|
8
|
+
# The code might have been modified to accommodate for the needs of this project
|
9
|
+
|
10
|
+
module Code0
|
11
|
+
module ZeroTrack
|
12
|
+
module Database
|
13
|
+
module SchemaMigrations
|
14
|
+
class Context
|
15
|
+
attr_reader :connection
|
16
|
+
|
17
|
+
class_attribute :default_schema_migrations_path, default: 'db/schema_migrations'
|
18
|
+
|
19
|
+
def initialize(connection)
|
20
|
+
@connection = connection
|
21
|
+
end
|
22
|
+
|
23
|
+
def schema_directory
|
24
|
+
@schema_directory ||= Rails.root.join(database_schema_migrations_path).to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def versions_to_create
|
28
|
+
versions_from_database = @connection.pool.schema_migration.versions
|
29
|
+
versions_from_migration_files = @connection.pool.migration_context.migrations.map { |m| m.version.to_s }
|
30
|
+
|
31
|
+
versions_from_database & versions_from_migration_files
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def database_name
|
37
|
+
@database_name ||= @connection.pool.db_config.name
|
38
|
+
end
|
39
|
+
|
40
|
+
def database_schema_migrations_path
|
41
|
+
@connection.pool.db_config.configuration_hash[:schema_migrations_path] ||
|
42
|
+
self.class.default_schema_migrations_path
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Heavily inspired by the implementation of GitLab
|
4
|
+
# (https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/lib/gitlab/database/schema_migrations/migrations.rb)
|
5
|
+
# which is licensed under a modified version of the MIT license which can be found at
|
6
|
+
# https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/LICENSE
|
7
|
+
#
|
8
|
+
# The code might have been modified to accommodate for the needs of this project
|
9
|
+
|
10
|
+
module Code0
|
11
|
+
module ZeroTrack
|
12
|
+
module Database
|
13
|
+
module SchemaMigrations
|
14
|
+
class Migrations
|
15
|
+
MIGRATION_VERSION_GLOB = '20[0-9][0-9]*'
|
16
|
+
|
17
|
+
def initialize(context)
|
18
|
+
@context = context
|
19
|
+
end
|
20
|
+
|
21
|
+
def touch_all
|
22
|
+
return unless @context.versions_to_create.any?
|
23
|
+
|
24
|
+
version_filepaths = version_filenames.map { |f| File.join(schema_directory, f) }
|
25
|
+
FileUtils.rm(version_filepaths)
|
26
|
+
|
27
|
+
@context.versions_to_create.each do |version|
|
28
|
+
version_filepath = File.join(schema_directory, version)
|
29
|
+
|
30
|
+
File.open(version_filepath, 'w') do |file|
|
31
|
+
file << Digest::SHA256.hexdigest(version)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_all
|
37
|
+
return if version_filenames.empty?
|
38
|
+
return unless @context.connection.pool.schema_migration.table_exists?
|
39
|
+
|
40
|
+
values = version_filenames.map { |vf| "('#{@context.connection.quote_string(vf)}')" }
|
41
|
+
|
42
|
+
@context.connection.execute(<<~SQL.squish)
|
43
|
+
INSERT INTO schema_migrations (version)
|
44
|
+
VALUES #{values.join(',')}
|
45
|
+
ON CONFLICT DO NOTHING
|
46
|
+
SQL
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def schema_directory
|
52
|
+
@context.schema_directory
|
53
|
+
end
|
54
|
+
|
55
|
+
def version_filenames
|
56
|
+
@version_filenames ||= Dir.glob(MIGRATION_VERSION_GLOB, base: schema_directory)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Heavily inspired by the implementation of GitLab
|
4
|
+
# (https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/lib/gitlab/database/schema_migrations.rb)
|
5
|
+
# which is licensed under a modified version of the MIT license which can be found at
|
6
|
+
# https://gitlab.com/gitlab-org/gitlab/-/blob/7983d2a2203aff265fae479d7c1b7066858d1265/LICENSE
|
7
|
+
#
|
8
|
+
# The code might have been modified to accommodate for the needs of this project
|
9
|
+
|
10
|
+
module Code0
|
11
|
+
module ZeroTrack
|
12
|
+
module Database
|
13
|
+
module SchemaMigrations
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def touch_all(connection)
|
17
|
+
context = Database::SchemaMigrations::Context.new(connection)
|
18
|
+
|
19
|
+
# rubocop:disable Rails/SkipsModelValidations -- not an active record object
|
20
|
+
Database::SchemaMigrations::Migrations.new(context).touch_all
|
21
|
+
# rubocop:enable Rails/SkipsModelValidations
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_all(connection)
|
25
|
+
context = Database::SchemaMigrations::Context.new(connection)
|
26
|
+
|
27
|
+
Database::SchemaMigrations::Migrations.new(context).load_all
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Injectors
|
6
|
+
class ActiveRecordSchemaMigrations
|
7
|
+
def self.inject!
|
8
|
+
# Patch to write version information as empty files under the db/schema_migrations directory
|
9
|
+
# This is intended to reduce potential for merge conflicts in db/structure.sql
|
10
|
+
ActiveSupport.on_load(:active_record_postgresqladapter) do
|
11
|
+
prepend Database::PostgresqlAdapter::DumpSchemaVersionsMixin
|
12
|
+
end
|
13
|
+
# Patch to load version information from empty files under the db/schema_migrations directory
|
14
|
+
ActiveRecord::Tasks::PostgreSQLDatabaseTasks
|
15
|
+
.prepend Database::PostgresqlDatabaseTasks::LoadSchemaVersionsMixin
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Injectors
|
6
|
+
class ActiveRecordTimestamps
|
7
|
+
def self.inject!
|
8
|
+
ActiveSupport.on_load(:active_record_postgresqladapter) do
|
9
|
+
self::NATIVE_DATABASE_TYPES[:datetime_with_timezone] = { name: 'timestamptz' }
|
10
|
+
end
|
11
|
+
|
12
|
+
ActiveSupport.on_load(:active_record) do
|
13
|
+
ActiveRecord::Base.time_zone_aware_types += [:datetime_with_timezone]
|
14
|
+
end
|
15
|
+
|
16
|
+
ActiveRecord::ConnectionAdapters::ColumnMethods.include ZeroTrack::Database::ColumnMethods::Timestamps
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Loggable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
class_methods do
|
9
|
+
def logger
|
10
|
+
Logger.new(Rails.logger, name || '<Anonymous>')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def logger
|
15
|
+
Logger.new(Rails.logger, self.class.name || '<Anonymous>')
|
16
|
+
end
|
17
|
+
|
18
|
+
class Logger
|
19
|
+
def initialize(log, clazz)
|
20
|
+
@log = log
|
21
|
+
@clazz = clazz
|
22
|
+
end
|
23
|
+
|
24
|
+
delegate :debug?, :info?, :warn?, :error?, :fatal?, :formatter, :level, to: :@log
|
25
|
+
|
26
|
+
def with_context(&block)
|
27
|
+
Code0::ZeroTrack::Context.with_context(class: @clazz, &block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def debug(message)
|
31
|
+
with_context { @log.debug(message) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def error(message)
|
35
|
+
with_context { @log.error(message) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def warn(message)
|
39
|
+
with_context { @log.warn(message) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def info(message)
|
43
|
+
with_context { @log.info(message) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Logs
|
6
|
+
class JsonFormatter < ::Logger::Formatter
|
7
|
+
def call(severity, datetime, _progname, message)
|
8
|
+
JSON.generate(data(severity, datetime, message)) << "\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
def data(severity, datetime, message)
|
12
|
+
data = {}
|
13
|
+
data[:severity] = severity
|
14
|
+
data[:time] = datetime.utc.iso8601(3)
|
15
|
+
|
16
|
+
case message
|
17
|
+
when String
|
18
|
+
data[:message] = chomp message
|
19
|
+
when Hash
|
20
|
+
data.merge!(message)
|
21
|
+
end
|
22
|
+
|
23
|
+
data.merge!(Code0::ZeroTrack::Context.current.to_h)
|
24
|
+
end
|
25
|
+
|
26
|
+
def chomp(message)
|
27
|
+
message.chomp! until message.chomp == message
|
28
|
+
|
29
|
+
message.strip
|
30
|
+
end
|
31
|
+
|
32
|
+
class Tagged < JsonFormatter
|
33
|
+
include ActiveSupport::TaggedLogging::Formatter
|
34
|
+
|
35
|
+
def tagged(*_args)
|
36
|
+
yield self # Ignore tags, they break the json layout as they are prepended to the log line
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Code0
|
4
|
+
module ZeroTrack
|
5
|
+
module Memoize
|
6
|
+
def memoize(name, reset_on_change: nil)
|
7
|
+
unless reset_on_change.nil?
|
8
|
+
reset_trigger = reset_on_change.call
|
9
|
+
reset_memoize = memoize("#{name}_reset_on_change") { reset_trigger }
|
10
|
+
|
11
|
+
if reset_trigger != reset_memoize
|
12
|
+
clear_memoize(name)
|
13
|
+
clear_memoize("#{name}_reset_on_change")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
if memoized?(name)
|
18
|
+
instance_variable_get(ivar(name))
|
19
|
+
else
|
20
|
+
instance_variable_set(ivar(name), yield)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def memoized?(name)
|
25
|
+
instance_variable_defined?(ivar(name))
|
26
|
+
end
|
27
|
+
|
28
|
+
def clear_memoize(name)
|
29
|
+
clear_memoize!(name) if memoized?(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear_memoize!(name)
|
33
|
+
remove_instance_variable(ivar(name))
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def ivar(name)
|
39
|
+
case name
|
40
|
+
when Symbol
|
41
|
+
name.to_s.prepend('@').to_sym
|
42
|
+
when String
|
43
|
+
:"@#{name}"
|
44
|
+
else
|
45
|
+
raise ArgumentError, "Invalid type of '#{name}'"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -3,6 +3,21 @@
|
|
3
3
|
module Code0
|
4
4
|
module ZeroTrack
|
5
5
|
class Railtie < ::Rails::Railtie
|
6
|
+
config.zero_track = ActiveSupport::OrderedOptions.new
|
7
|
+
config.zero_track.active_record = ActiveSupport::OrderedOptions.new
|
8
|
+
config.zero_track.active_record.timestamps = false
|
9
|
+
config.zero_track.active_record.schema_migrations = false
|
10
|
+
config.zero_track.active_record.schema_cleaner = false
|
11
|
+
|
12
|
+
rake_tasks do
|
13
|
+
path = File.expand_path(__dir__)
|
14
|
+
Dir.glob("#{path}/../../tasks/**/*.rake").each { |f| load f }
|
15
|
+
end
|
16
|
+
|
17
|
+
config.after_initialize do
|
18
|
+
Injectors::ActiveRecordTimestamps.inject! if config.zero_track.active_record.timestamps
|
19
|
+
Injectors::ActiveRecordSchemaMigrations.inject! if config.zero_track.active_record.schema_migrations
|
20
|
+
end
|
6
21
|
end
|
7
22
|
end
|
8
23
|
end
|
data/lib/code0/zero_track.rb
CHANGED
@@ -1,10 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
3
|
+
require 'rails/railtie'
|
4
|
+
|
5
|
+
require 'zeitwerk'
|
6
|
+
loader = Zeitwerk::Loader.new
|
7
|
+
loader.tag = File.basename(__FILE__, '.rb')
|
8
|
+
loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
|
9
|
+
loader.push_dir(File.expand_path(File.join(__dir__, '..')))
|
10
|
+
loader.setup
|
5
11
|
|
6
12
|
module Code0
|
7
13
|
module ZeroTrack
|
8
14
|
# Your code goes here...
|
9
15
|
end
|
10
16
|
end
|
17
|
+
|
18
|
+
Code0::ZeroTrack::Railtie # eager load the railtie
|
@@ -1,6 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
namespace :code0 do
|
4
|
+
namespace :zero_track do
|
5
|
+
namespace :db do
|
6
|
+
desc 'This adjusts and cleans db/structure.sql - it runs after db:schema:dump'
|
7
|
+
task clean_structure_sql: :environment do |task_name|
|
8
|
+
# Allow this task to be called multiple times, as happens when running db:migrate:redo
|
9
|
+
Rake::Task[task_name].reenable
|
10
|
+
|
11
|
+
next unless Rails.application.config.zero_track.active_record.schema_cleaner
|
12
|
+
|
13
|
+
ActiveRecord::Base.configurations
|
14
|
+
.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
|
15
|
+
.each do |db_config|
|
16
|
+
structure_file = ActiveRecord::Tasks::DatabaseTasks.schema_dump_path(db_config)
|
17
|
+
|
18
|
+
schema = File.read(structure_file)
|
19
|
+
|
20
|
+
File.open(structure_file, 'wb+') do |io|
|
21
|
+
Code0::ZeroTrack::Database::SchemaCleaner.new(schema).clean(io)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Inform Rake that custom tasks should be run every time rake db:schema:dump is run
|
27
|
+
Rake::Task['db:schema:dump'].enhance do
|
28
|
+
Rake::Task['code0:zero_track:db:clean_structure_sql'].invoke
|
29
|
+
end
|
30
|
+
Rake::Task['db:prepare'].enhance do
|
31
|
+
Rake::Task['code0:zero_track:db:clean_structure_sql'].invoke
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: code0-zero_track
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Niklas van Schrick
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 8.0.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: zeitwerk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.7'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +66,20 @@ dependencies:
|
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-parameterized
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: rspec-rails
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,7 +150,7 @@ dependencies:
|
|
122
150
|
- - "~>"
|
123
151
|
- !ruby/object:Gem::Version
|
124
152
|
version: '2.30'
|
125
|
-
description:
|
153
|
+
description:
|
126
154
|
email:
|
127
155
|
- mc.taucher2003@gmail.com
|
128
156
|
executables: []
|
@@ -133,6 +161,24 @@ files:
|
|
133
161
|
- README.md
|
134
162
|
- Rakefile
|
135
163
|
- lib/code0/zero_track.rb
|
164
|
+
- lib/code0/zero_track/context.rb
|
165
|
+
- lib/code0/zero_track/database/column_methods.rb
|
166
|
+
- lib/code0/zero_track/database/migration.rb
|
167
|
+
- lib/code0/zero_track/database/migration_helpers/add_column_enhancements.rb
|
168
|
+
- lib/code0/zero_track/database/migration_helpers/constraint_helpers.rb
|
169
|
+
- lib/code0/zero_track/database/migration_helpers/index_helpers.rb
|
170
|
+
- lib/code0/zero_track/database/migration_helpers/table_enhancements.rb
|
171
|
+
- lib/code0/zero_track/database/postgresql_adapter/dump_schema_versions_mixin.rb
|
172
|
+
- lib/code0/zero_track/database/postgresql_database_tasks/load_schema_versions_mixin.rb
|
173
|
+
- lib/code0/zero_track/database/schema_cleaner.rb
|
174
|
+
- lib/code0/zero_track/database/schema_migrations.rb
|
175
|
+
- lib/code0/zero_track/database/schema_migrations/context.rb
|
176
|
+
- lib/code0/zero_track/database/schema_migrations/migrations.rb
|
177
|
+
- lib/code0/zero_track/injectors/active_record_schema_migrations.rb
|
178
|
+
- lib/code0/zero_track/injectors/active_record_timestamps.rb
|
179
|
+
- lib/code0/zero_track/loggable.rb
|
180
|
+
- lib/code0/zero_track/logs/json_formatter.rb
|
181
|
+
- lib/code0/zero_track/memoize.rb
|
136
182
|
- lib/code0/zero_track/railtie.rb
|
137
183
|
- lib/code0/zero_track/version.rb
|
138
184
|
- lib/tasks/code0/zero_track_tasks.rake
|
@@ -144,7 +190,7 @@ metadata:
|
|
144
190
|
source_code_uri: https://github.com/code0-tech/code0-zero_track
|
145
191
|
changelog_uri: https://github.com/code0-tech/code0-zero_track/releases
|
146
192
|
rubygems_mfa_required: 'true'
|
147
|
-
post_install_message:
|
193
|
+
post_install_message:
|
148
194
|
rdoc_options: []
|
149
195
|
require_paths:
|
150
196
|
- lib
|
@@ -152,7 +198,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
152
198
|
requirements:
|
153
199
|
- - ">="
|
154
200
|
- !ruby/object:Gem::Version
|
155
|
-
version: 3.
|
201
|
+
version: 3.2.0
|
156
202
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
203
|
requirements:
|
158
204
|
- - ">="
|
@@ -160,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
206
|
version: '0'
|
161
207
|
requirements: []
|
162
208
|
rubygems_version: 3.4.10
|
163
|
-
signing_key:
|
209
|
+
signing_key:
|
164
210
|
specification_version: 4
|
165
211
|
summary: Common helpers for Code0 rails applications
|
166
212
|
test_files: []
|