gooddata 2.1.12 → 2.1.19
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/.gdc-ii-config.yaml +1 -1
- data/.sonar.settings +4 -0
- data/.travis.yml +78 -12
- data/CHANGELOG.md +37 -0
- data/Dockerfile +9 -3
- data/Dockerfile.jruby +11 -1
- data/LICENSE +30 -22
- data/LICENSE.rb +1 -1
- data/README.md +19 -1
- data/Rakefile +8 -1
- data/SDK_VERSION +1 -1
- data/VERSION +1 -1
- data/bin/test_projects_cleanup.rb +45 -3
- data/ci/postgresql/pom.xml +57 -0
- data/dev-gooddata-sso.pub.encrypted +40 -40
- data/docker-compose.lcm.yml +3 -0
- data/gdc_fossa_ruby_sdk.yaml +1 -0
- data/gooddata.gemspec +8 -5
- data/k8s/charts/lcm-bricks/Chart.yaml +1 -1
- data/k8s/charts/lcm-bricks/templates/prometheus/alertingRules.yaml +11 -1
- data/lcm.rake +10 -4
- data/lib/gooddata.rb +2 -0
- data/lib/gooddata/cloud_resources/{cloud_resouce_factory.rb → cloud_resource_factory.rb} +8 -0
- data/lib/gooddata/cloud_resources/cloud_resources.rb +1 -1
- data/lib/gooddata/cloud_resources/postgresql/drivers/.gitkeepme +0 -0
- data/lib/gooddata/cloud_resources/postgresql/postgresql_client.rb +107 -0
- data/lib/gooddata/commands/scaffold.rb +9 -10
- data/lib/gooddata/core/nil_logger.rb +3 -1
- data/lib/gooddata/helpers/data_helper.rb +1 -2
- data/lib/gooddata/helpers/global_helpers.rb +6 -5
- data/lib/gooddata/helpers/global_helpers_params.rb +2 -2
- data/lib/gooddata/lcm/actions/associate_clients.rb +8 -2
- data/lib/gooddata/lcm/actions/base_action.rb +0 -2
- data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +2 -1
- data/lib/gooddata/lcm/actions/migrate_gdc_date_dimension.rb +116 -0
- data/lib/gooddata/lcm/actions/provision_clients.rb +31 -10
- data/lib/gooddata/lcm/actions/synchronize_ldm.rb +3 -1
- data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +4 -0
- data/lib/gooddata/lcm/actions/synchronize_users.rb +7 -6
- data/lib/gooddata/lcm/lcm2.rb +1 -2
- data/lib/gooddata/lcm/types/base_type.rb +0 -2
- data/lib/gooddata/mixins/md_object_query.rb +8 -6
- data/lib/gooddata/models/blueprint/project_blueprint.rb +0 -2
- data/lib/gooddata/models/client.rb +14 -12
- data/lib/gooddata/models/data_source.rb +664 -0
- data/lib/gooddata/models/domain.rb +3 -2
- data/lib/gooddata/models/from_wire.rb +1 -0
- data/lib/gooddata/models/metadata/analytical_dashboard.rb +49 -0
- data/lib/gooddata/models/metadata/analytical_visualization_object.rb +30 -0
- data/lib/gooddata/models/metadata/scheduled_mail.rb +1 -1
- data/lib/gooddata/models/metadata/visualization_object.rb +50 -0
- data/lib/gooddata/models/process.rb +11 -3
- data/lib/gooddata/models/project.rb +104 -13
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +0 -1
- data/lib/gooddata/models/user_group.rb +0 -1
- data/lib/gooddata/rest/connection.rb +6 -4
- data/lib/gooddata/rest/phmap.rb +1 -1
- data/rubydev_public.gpg.encrypted +51 -51
- data/rubydev_secret_keys.gpg.encrypted +109 -109
- metadata +21 -22
- data/DEPENDENCIES.md +0 -880
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
4
|
+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
5
|
+
<modelVersion>4.0.0</modelVersion>
|
|
6
|
+
|
|
7
|
+
<groupId>com.gooddata.lcm</groupId>
|
|
8
|
+
<artifactId>lcm-postgresql-driver</artifactId>
|
|
9
|
+
<version>1.0-SNAPSHOT</version>
|
|
10
|
+
|
|
11
|
+
<dependencies>
|
|
12
|
+
<dependency>
|
|
13
|
+
<groupId>org.postgresql</groupId>
|
|
14
|
+
<artifactId>postgresql</artifactId>
|
|
15
|
+
<version>42.2.19</version>
|
|
16
|
+
</dependency>
|
|
17
|
+
<dependency>
|
|
18
|
+
<groupId>org.slf4j</groupId>
|
|
19
|
+
<artifactId>slf4j-api</artifactId>
|
|
20
|
+
<version>1.7.2</version>
|
|
21
|
+
</dependency>
|
|
22
|
+
</dependencies>
|
|
23
|
+
|
|
24
|
+
<profiles>
|
|
25
|
+
<profile>
|
|
26
|
+
<id>binary-packaging</id>
|
|
27
|
+
<build>
|
|
28
|
+
<plugins>
|
|
29
|
+
<plugin>
|
|
30
|
+
<artifactId>maven-dependency-plugin</artifactId>
|
|
31
|
+
<executions>
|
|
32
|
+
<execution>
|
|
33
|
+
<phase>package</phase>
|
|
34
|
+
<goals>
|
|
35
|
+
<goal>copy-dependencies</goal>
|
|
36
|
+
</goals>
|
|
37
|
+
<configuration>
|
|
38
|
+
<outputDirectory>${project.build.directory}</outputDirectory>
|
|
39
|
+
<!-- compile scope gives runtime and compile dependencies (skips test deps) -->
|
|
40
|
+
<includeScope>runtime</includeScope>
|
|
41
|
+
</configuration>
|
|
42
|
+
</execution>
|
|
43
|
+
</executions>
|
|
44
|
+
</plugin>
|
|
45
|
+
</plugins>
|
|
46
|
+
</build>
|
|
47
|
+
</profile>
|
|
48
|
+
</profiles>
|
|
49
|
+
|
|
50
|
+
<repositories>
|
|
51
|
+
<repository>
|
|
52
|
+
<id>my-repo1</id>
|
|
53
|
+
<name>my custom repo</name>
|
|
54
|
+
<url>https://repository.mulesoft.org/nexus/content/repositories/public/</url>
|
|
55
|
+
</repository>
|
|
56
|
+
</repositories>
|
|
57
|
+
</project>
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
+
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
1
|
+
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
|
|
40
|
+
N/WeNcE=
|
data/docker-compose.lcm.yml
CHANGED
data/gdc_fossa_ruby_sdk.yaml
CHANGED
data/gooddata.gemspec
CHANGED
|
@@ -5,7 +5,7 @@ require 'gooddata/version'
|
|
|
5
5
|
Gem::Specification.new do |s|
|
|
6
6
|
s.name = 'gooddata'
|
|
7
7
|
s.version = GoodData::VERSION
|
|
8
|
-
s.licenses = ['BSD']
|
|
8
|
+
s.licenses = ['BSD-3-Clause']
|
|
9
9
|
s.platform = 'java' if RUBY_PLATFORM =~ /java/
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
|
|
|
24
24
|
s.email = 'lcm@gooddata.com'
|
|
25
25
|
s.extra_rdoc_files = %w(LICENSE README.md)
|
|
26
26
|
|
|
27
|
-
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
27
|
+
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR).map { |f| f unless %w(NOTICES.txt LICENSE_FOR_RUBY_SDK_COMPONENT.txt).include?(f) }
|
|
28
28
|
s.files.reject! { |fn| fn.start_with? 'spec/' }
|
|
29
29
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
30
30
|
|
|
@@ -55,14 +55,17 @@ Gem::Specification.new do |s|
|
|
|
55
55
|
s.add_development_dependency 'sqlite3' if RUBY_PLATFORM != 'java'
|
|
56
56
|
|
|
57
57
|
if RUBY_VERSION >= '2.5'
|
|
58
|
-
s.add_dependency 'activesupport', '>= 6.0.3.1', '< 6.
|
|
58
|
+
s.add_dependency 'activesupport', '>= 6.0.3.1', '< 6.2'
|
|
59
59
|
else
|
|
60
60
|
s.add_dependency 'activesupport', '>= 5.2.4.3', '< 6.0'
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
s.add_dependency 'aws-sdk-s3', '~> 1.16'
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
if RUBY_VERSION >= '2.5'
|
|
65
|
+
s.add_dependency 'docile', '~> 1.1'
|
|
66
|
+
else
|
|
67
|
+
s.add_dependency 'docile', '> 1.1', '< 1.4.0'
|
|
68
|
+
end
|
|
66
69
|
s.add_dependency 'gli', '~> 2.15'
|
|
67
70
|
s.add_dependency 'gooddata_datawarehouse', '~> 0.0.10' if RUBY_PLATFORM == 'java'
|
|
68
71
|
s.add_dependency 'highline', '= 2.0.0.pre.develop.14'
|
|
@@ -92,4 +92,14 @@ data:
|
|
|
92
92
|
annotations:
|
|
93
93
|
description: "We are hitting CPU limit in LCM namespace."
|
|
94
94
|
summary: "We are hitting CPU limit in LCM namespace."
|
|
95
|
-
|
|
95
|
+
- alert: "[LCM] POD is in undesirable state on cluster={{ .Values.clusterId }}"
|
|
96
|
+
expr: kube_pod_status_phase{namespace='{{ .Release.Namespace }}', phase!~"Running|Succeeded|Failed"} > 0
|
|
97
|
+
for: 5m
|
|
98
|
+
labels:
|
|
99
|
+
cluster_id: {{ .Values.clusterId }}
|
|
100
|
+
severity: critical
|
|
101
|
+
team: lcm
|
|
102
|
+
annotations:
|
|
103
|
+
description: "POD {{`{{ $labels.pod }}`}} is not in desirable state"
|
|
104
|
+
summary: "POD is not in desirable state"
|
|
105
|
+
runbook: "https://confluence.intgdc.com/display/plat/Generic+runbooks#Genericrunbooks-Podisinundesirablestate"
|
data/lcm.rake
CHANGED
|
@@ -3,7 +3,7 @@ require 'fileutils'
|
|
|
3
3
|
require 'pathname'
|
|
4
4
|
require 'rspec/core/rake_task'
|
|
5
5
|
|
|
6
|
-
test_cases = %i[integration slow userprov load]
|
|
6
|
+
test_cases = %i[integration-e2e integration-release integration-others slow userprov load]
|
|
7
7
|
|
|
8
8
|
# Schema for new Bricks.
|
|
9
9
|
brick_info_schema = {
|
|
@@ -79,7 +79,7 @@ namespace :test do
|
|
|
79
79
|
test_cases.each do |test_case|
|
|
80
80
|
desc "Run #{test_case} tests"
|
|
81
81
|
RSpec::Core::RakeTask.new(test_case) do |task|
|
|
82
|
-
task.pattern = "spec/lcm/#{test_case}/**/*_spec.rb"
|
|
82
|
+
task.pattern = test_case['integration'] ? "spec/lcm/integration/spec/#{test_case.to_s.split('-')[-1]}/*_spec.rb" : "spec/lcm/#{test_case}/**/*_spec.rb"
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
|
|
@@ -101,8 +101,14 @@ namespace :test do
|
|
|
101
101
|
test_cases.each do |t|
|
|
102
102
|
desc "Run #{t} tests in Docker"
|
|
103
103
|
task t do
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
if t.to_s == 'integration'
|
|
105
|
+
system("docker-compose -f docker-compose.lcm.yml run --rm appstore /bin/bash -c ./spec/integration_with_postgresql.sh") ||
|
|
106
|
+
fail('Test execution failed!')
|
|
107
|
+
else
|
|
108
|
+
system("docker-compose -f docker-compose.lcm.yml run --rm appstore bundle exec rake -f lcm.rake test:#{t}") ||
|
|
109
|
+
fail('Test execution failed!')
|
|
110
|
+
end
|
|
111
|
+
|
|
106
112
|
end
|
|
107
113
|
end
|
|
108
114
|
end
|
data/lib/gooddata.rb
CHANGED
|
@@ -11,7 +11,15 @@ module GoodData
|
|
|
11
11
|
module CloudResources
|
|
12
12
|
class CloudResourceFactory
|
|
13
13
|
class << self
|
|
14
|
+
def load_cloud_resource(type)
|
|
15
|
+
base = "#{Pathname(__FILE__).dirname.expand_path}#{File::SEPARATOR}#{type}#{File::SEPARATOR}"
|
|
16
|
+
Dir.glob(base + '**/*.rb').each do |file|
|
|
17
|
+
require file
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
14
21
|
def create(type, data = {}, opts = {})
|
|
22
|
+
load_cloud_resource(type)
|
|
15
23
|
clients = CloudResourceClient.descendants.select { |c| c.respond_to?("accept?") && c.send("accept?", type) }
|
|
16
24
|
raise "DataSource does not support type \"#{type}\"" if clients.empty?
|
|
17
25
|
|
|
File without changes
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2021 GoodData Corporation. All rights reserved.
|
|
5
|
+
# This source code is licensed under the BSD-style license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
require 'securerandom'
|
|
9
|
+
require 'java'
|
|
10
|
+
require 'pathname'
|
|
11
|
+
require_relative '../cloud_resource_client'
|
|
12
|
+
|
|
13
|
+
base = Pathname(__FILE__).dirname.expand_path
|
|
14
|
+
Dir.glob(base + 'drivers/*.jar').each do |file|
|
|
15
|
+
require file unless file.start_with?('lcm-postgresql-driver')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module GoodData
|
|
19
|
+
module CloudResources
|
|
20
|
+
class PostgresClient < CloudResourceClient
|
|
21
|
+
JDBC_POSTGRES_PATTERN = %r{jdbc:postgresql:\/\/([^:^\/]+)(:([0-9]+))?(\/)?}
|
|
22
|
+
POSTGRES_DEFAULT_PORT = 5432
|
|
23
|
+
JDBC_POSTGRES_PROTOCOL = 'jdbc:postgresql://'
|
|
24
|
+
SSL_JAVA_FACTORY = '&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory'
|
|
25
|
+
VERIFY_FULL = 'verify-full'
|
|
26
|
+
PREFER = 'prefer'
|
|
27
|
+
REQUIRE = 'require'
|
|
28
|
+
POSTGRES_SET_SCHEMA_COMMAND = "set search_path to"
|
|
29
|
+
POSTGRES_FETCH_SIZE = 1000
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
def accept?(type)
|
|
33
|
+
type == 'postgresql'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def initialize(options = {})
|
|
38
|
+
raise("Data Source needs a client to Postgres to be able to query the storage but 'postgresql_client' is empty.") unless options['postgresql_client']
|
|
39
|
+
|
|
40
|
+
if options['postgresql_client']['connection'].is_a?(Hash)
|
|
41
|
+
@database = options['postgresql_client']['connection']['database']
|
|
42
|
+
@schema = options['postgresql_client']['connection']['schema'] || 'public'
|
|
43
|
+
@authentication = options['postgresql_client']['connection']['authentication']
|
|
44
|
+
@ssl_mode = options['postgresql_client']['connection']['sslMode']
|
|
45
|
+
raise "SSL Mode should be prefer, require and verify-full" unless @ssl_mode == 'prefer' || @ssl_mode == 'require' || @ssl_mode == 'verify-full'
|
|
46
|
+
|
|
47
|
+
@url = build_url(options['postgresql_client']['connection']['url'])
|
|
48
|
+
else
|
|
49
|
+
raise('Missing connection info for Postgres client')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Java.org.postgresql.Driver
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def realize_query(query, _params)
|
|
56
|
+
GoodData.gd_logger.info("Realize SQL query: type=postgresql status=started")
|
|
57
|
+
|
|
58
|
+
connect
|
|
59
|
+
filename = "#{SecureRandom.urlsafe_base64(6)}_#{Time.now.to_i}.csv"
|
|
60
|
+
measure = Benchmark.measure do
|
|
61
|
+
statement = @connection.create_statement
|
|
62
|
+
statement.set_fetch_size(POSTGRES_FETCH_SIZE)
|
|
63
|
+
has_result = statement.execute(query)
|
|
64
|
+
if has_result
|
|
65
|
+
result = statement.get_result_set
|
|
66
|
+
metadata = result.get_meta_data
|
|
67
|
+
col_count = metadata.column_count
|
|
68
|
+
CSV.open(filename, 'wb') do |csv|
|
|
69
|
+
csv << Array(1..col_count).map { |i| metadata.get_column_name(i) } # build the header
|
|
70
|
+
csv << Array(1..col_count).map { |i| result.get_string(i)&.to_s } while result.next
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
GoodData.gd_logger.info("Realize SQL query: type=postgresql status=finished duration=#{measure.real}")
|
|
75
|
+
filename
|
|
76
|
+
ensure
|
|
77
|
+
@connection&.close
|
|
78
|
+
@connection = nil
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def connect
|
|
82
|
+
GoodData.logger.info "Setting up connection to Postgresql #{@url}"
|
|
83
|
+
|
|
84
|
+
prop = java.util.Properties.new
|
|
85
|
+
prop.setProperty('user', @authentication['basic']['userName'])
|
|
86
|
+
prop.setProperty('password', @authentication['basic']['password'])
|
|
87
|
+
prop.setProperty('schema', @schema)
|
|
88
|
+
|
|
89
|
+
@connection = java.sql.DriverManager.getConnection(@url, prop)
|
|
90
|
+
statement = @connection.create_statement
|
|
91
|
+
statement.execute("#{POSTGRES_SET_SCHEMA_COMMAND} #{@schema}")
|
|
92
|
+
@connection.set_auto_commit(false)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build_url(url)
|
|
96
|
+
matches = url.scan(JDBC_POSTGRES_PATTERN)
|
|
97
|
+
raise 'Cannot reach the url' unless matches
|
|
98
|
+
|
|
99
|
+
host = matches[0][0]
|
|
100
|
+
port = matches[0][2]&.to_i || POSTGRES_DEFAULT_PORT
|
|
101
|
+
raise "Custom port #{port} is not supported. Remove it or use the default port '5432'" if POSTGRES_DEFAULT_PORT != port
|
|
102
|
+
|
|
103
|
+
"#{JDBC_POSTGRES_PROTOCOL}#{host}:#{port}/#{@database}?sslmode=#{@ssl_mode}#{VERIFY_FULL == @ssl_mode ? SSL_JAVA_FACTORY : ''}"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This source code is licensed under the BSD-style license found in the
|
|
5
5
|
# LICENSE file in the root directory of this source tree.
|
|
6
6
|
|
|
7
|
-
require '
|
|
7
|
+
require 'erb'
|
|
8
8
|
require 'fileutils'
|
|
9
9
|
require 'pathname'
|
|
10
10
|
|
|
@@ -18,15 +18,14 @@ module GoodData
|
|
|
18
18
|
# TODO: Add option for custom output dir
|
|
19
19
|
def project(name)
|
|
20
20
|
fail ArgumentError, 'No name specified' if name.nil?
|
|
21
|
-
|
|
22
21
|
FileUtils.mkdir(name)
|
|
23
22
|
FileUtils.cd(name) do
|
|
24
23
|
FileUtils.mkdir('model')
|
|
25
24
|
FileUtils.cd('model') do
|
|
26
25
|
input = File.read(TEMPLATES_PATH + 'project/model/model.rb.erb')
|
|
27
|
-
|
|
26
|
+
erb = ERB.new(input)
|
|
28
27
|
File.open('model.rb', 'w') do |f|
|
|
29
|
-
f.write(
|
|
28
|
+
f.write(erb.result_with_hash(:name => name))
|
|
30
29
|
end
|
|
31
30
|
end
|
|
32
31
|
|
|
@@ -36,9 +35,9 @@ module GoodData
|
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
input = File.read(TEMPLATES_PATH + 'project/Goodfile.erb')
|
|
39
|
-
|
|
38
|
+
erb = ERB.new(input)
|
|
40
39
|
File.open('Goodfile', 'w') do |f|
|
|
41
|
-
f.write(
|
|
40
|
+
f.write(erb.result)
|
|
42
41
|
end
|
|
43
42
|
end
|
|
44
43
|
end
|
|
@@ -51,15 +50,15 @@ module GoodData
|
|
|
51
50
|
FileUtils.mkdir(name)
|
|
52
51
|
FileUtils.cd(name) do
|
|
53
52
|
input = File.read(TEMPLATES_PATH + 'bricks/brick.rb.erb')
|
|
54
|
-
|
|
53
|
+
erb = ERB.new(input)
|
|
55
54
|
File.open('brick.rb', 'w') do |f|
|
|
56
|
-
f.write(
|
|
55
|
+
f.write(erb.result)
|
|
57
56
|
end
|
|
58
57
|
|
|
59
58
|
input = File.read(TEMPLATES_PATH + 'bricks/main.rb.erb')
|
|
60
|
-
|
|
59
|
+
erb = ERB.new(input)
|
|
61
60
|
File.open('main.rb', 'w') do |f|
|
|
62
|
-
f.write(
|
|
61
|
+
f.write(erb.result)
|
|
63
62
|
end
|
|
64
63
|
end
|
|
65
64
|
end
|