Skip to content

Commit e33764f

Browse files
authored
Merge pull request #707 from cloudfoundry/add-ruby-workflow
Add Ruby workflow for embedded ruby code
2 parents 1e921fd + b387a21 commit e33764f

File tree

7 files changed

+147
-26
lines changed

7 files changed

+147
-26
lines changed

.github/workflows/ruby.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Run Specs
2+
on: [push, pull_request]
3+
4+
jobs:
5+
test_embedded_ruby:
6+
strategy:
7+
matrix:
8+
os: [ubuntu-latest, macos-latest]
9+
ruby: [ '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4', head]
10+
runs-on: ${{ matrix.os }}
11+
steps:
12+
- uses: actions/checkout@v6
13+
- uses: ruby/setup-ruby@v1
14+
with:
15+
ruby-version: ${{ matrix.ruby }}
16+
- run: bundle install
17+
working-directory: templatescompiler/erbrenderer/
18+
- run: bundle exec rake
19+
working-directory: templatescompiler/erbrenderer/
20+
continue-on-error: ${{ matrix.ruby == 'head' }}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Gemfile.lock
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
source "https://rubygems.org"
2+
3+
group :test do
4+
gem "rake"
5+
gem "rspec"
6+
gem "standardrb"
7+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
require "rspec/core/rake_task"
2+
require "standard/rake"
3+
4+
RSpec::Core::RakeTask.new(:spec)
5+
6+
task default: [:standard, :spec]

templatescompiler/erbrenderer/erb_renderer.rb

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
class Hash
99
def recursive_merge!(other)
10-
self.merge!(other) do |_, old_value, new_value|
11-
if old_value.class == Hash && new_value.class == Hash
10+
merge!(other) do |_, old_value, new_value|
11+
if old_value.class == Hash && new_value.class == Hash # rubocop:disable Style/ClassEqualityComparison
1212
old_value.recursive_merge!(new_value)
1313
else
1414
new_value
@@ -27,14 +27,14 @@ def initialize(spec)
2727
@name = spec["job"]["name"] if spec["job"].is_a?(Hash)
2828
@index = spec["index"]
2929

30-
if !spec['job_properties'].nil?
31-
properties1 = spec['job_properties']
30+
properties1 = if !spec["job_properties"].nil?
31+
spec["job_properties"]
3232
else
33-
properties1 = spec['global_properties'].recursive_merge!(spec['cluster_properties'])
33+
spec["global_properties"].recursive_merge!(spec["cluster_properties"])
3434
end
3535

3636
properties = {}
37-
spec['default_properties'].each do |name, value|
37+
spec["default_properties"].each do |name, value|
3838
copy_property(properties, properties1, name, value)
3939
end
4040

@@ -66,7 +66,7 @@ def if_p(*names)
6666
value
6767
end
6868

69-
yield *values
69+
yield(*values)
7070
InactiveElseBlock.new
7171
end
7272

@@ -97,13 +97,15 @@ def copy_property(dst, src, name, default = nil)
9797

9898
def openstruct(object)
9999
case object
100-
when Hash
101-
mapped = object.inject({}) { |h, (k,v)| h[k] = openstruct(v); h }
102-
OpenStruct.new(mapped)
103-
when Array
104-
object.map { |item| openstruct(item) }
105-
else
106-
object
100+
when Hash
101+
mapped = object.each_with_object({}) { |(k, v), h|
102+
h[k] = openstruct(v)
103+
}
104+
OpenStruct.new(mapped)
105+
when Array
106+
object.map { |item| openstruct(item) }
107+
else
108+
object
107109
end
108110
end
109111

@@ -137,13 +139,14 @@ def else
137139
yield
138140
end
139141

140-
def else_if_p(*names, &block)
141-
@context.if_p(*names, &block)
142+
def else_if_p(*names, &block) # rubocop:disable Style/ArgumentsForwarding
143+
@context.if_p(*names, &block) # rubocop:disable Style/ArgumentsForwarding
142144
end
143145
end
144146

145147
class InactiveElseBlock
146-
def else; end
148+
def else
149+
end
147150

148151
def else_if_p(*names)
149152
InactiveElseBlock.new
@@ -153,7 +156,7 @@ def else_if_p(*names)
153156

154157
# todo do not use JSON in releases
155158
class << JSON
156-
alias dump_array_or_hash dump
159+
alias_method :dump_array_or_hash, :dump
157160

158161
def dump(*args)
159162
arg = args[0]
@@ -174,18 +177,16 @@ def render(src_path, dst_path)
174177
erb = ERB.new(File.read(src_path), trim_mode: "-")
175178
erb.filename = src_path
176179

177-
context_hash = JSON.load(File.read(@json_context_path))
180+
# Note: JSON.load_file was added in v2.3.1: https://github.com/ruby/json/blob/v2.3.1/lib/json/common.rb#L286
181+
context_hash = JSON.parse(File.read(@json_context_path))
178182
template_evaluation_context = TemplateEvaluationContext.new(context_hash)
179183

180-
File.open(dst_path, "w") do |f|
181-
f.write(erb.result(template_evaluation_context.get_binding))
182-
end
183-
184-
rescue Exception => e
184+
File.write(dst_path, erb.result(template_evaluation_context.get_binding))
185+
rescue Exception => e # rubocop:disable Lint/RescueException
185186
name = "#{template_evaluation_context&.name}/#{template_evaluation_context&.index}"
186187

187-
line_i = e.backtrace.index { |l| l.include?("#{erb&.filename}") }
188-
line_num = line_i ? e.backtrace[line_i].split(':')[1] : "unknown"
188+
line_i = e.backtrace.index { |l| l.include?(erb&.filename.to_s) }
189+
line_num = line_i ? e.backtrace[line_i].split(":")[1] : "unknown"
189190
location = "(line #{line_num}: #{e.inspect})"
190191

191192
raise("Error filling in template '#{src_path}' for #{name} #{location}")
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
require "spec_helper"
2+
require "erb_renderer"
3+
4+
RSpec.describe "erb_renderer" do
5+
describe "ERBRenderer" do
6+
let(:test_tmpdir) { Dir.tmpdir }
7+
let(:json_context_path) { File.join(test_tmpdir, "context.json") }
8+
9+
before do
10+
File.write(json_context_path, context_hash.to_json)
11+
end
12+
13+
after do
14+
File.unlink(json_context_path) if File.exist?(json_context_path)
15+
end
16+
17+
describe "#initialize" do
18+
let(:context_hash) { {} }
19+
20+
it "does not raise an error" do
21+
expect { ERBRenderer.new(json_context_path) }.not_to raise_error
22+
end
23+
end
24+
25+
describe "#render" do
26+
let(:context_hash) do
27+
{
28+
index: 867_5309,
29+
global_properties: {
30+
property1: "global_value1"
31+
},
32+
cluster_properties: {
33+
property2: "cluster_value1"
34+
},
35+
default_properties: {
36+
property1: "default_value1",
37+
property2: "default_value2",
38+
property3: "default_value3"
39+
}
40+
}
41+
end
42+
43+
let(:erb_template_path) { File.join(test_tmpdir, "template.yml.erb") }
44+
let(:erb_content) do
45+
<<~TEST_TEMPLATE
46+
---
47+
property1: <%= p('property1') %>
48+
property2: <%= p('property2') %>
49+
property3: <%= p('property3') %>
50+
TEST_TEMPLATE
51+
end
52+
53+
let(:rendered_template_path) { File.join(test_tmpdir, "template.yml") }
54+
let(:expected_template_content) do
55+
<<~EXPECTED_TEMPLATE
56+
---
57+
property1: global_value1
58+
property2: cluster_value1
59+
property3: default_value3
60+
EXPECTED_TEMPLATE
61+
end
62+
63+
let(:erb_renderer) { ERBRenderer.new(json_context_path) }
64+
65+
before do
66+
File.write(erb_template_path, erb_content)
67+
end
68+
69+
it "does not raise an error" do
70+
expect { erb_renderer.render(erb_template_path, rendered_template_path) }.not_to raise_error
71+
end
72+
73+
it "renders the expected content" do
74+
erb_renderer.render(erb_template_path, rendered_template_path)
75+
expect(File.read(rendered_template_path)).to eq(expected_template_content)
76+
end
77+
end
78+
end
79+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require "rspec"
2+
require "json"
3+
require "tmpdir"
4+
5+
ERB_RENDERER_ROOT = File.expand_path("..", File.dirname(__FILE__))
6+
7+
$LOAD_PATH.unshift(ERB_RENDERER_ROOT)

0 commit comments

Comments
 (0)