Skip to content

Commit 166156b

Browse files
committed
WIP
1 parent 9c8d52b commit 166156b

File tree

4 files changed

+329
-15
lines changed

4 files changed

+329
-15
lines changed

.github/workflows/test.yml

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Please do NOT manually edit this file.
2+
# This file is generated by 'bundle exec rake github:actions:test_template'
3+
---
4+
name: Test
5+
'on':
6+
- push
7+
concurrency:
8+
group: "${{ github.workflow }}-${{ github.ref }}"
9+
cancel-in-progress: "${{ github.ref != 'refs/heads/master' }}"
10+
jobs:
11+
compute_tasks:
12+
runs-on: ubuntu-22.04
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
engine:
17+
- name: ruby
18+
version: '3.3'
19+
alias: ruby-33
20+
- name: ruby
21+
version: '3.2'
22+
alias: ruby-32
23+
container:
24+
image: ghcr.io/datadog/images-rb/engines/${{ matrix.engine.name }}:${{ matrix.engine.version }}
25+
outputs:
26+
ruby-33-matrix: "${{ steps.set-matrix.outputs.ruby-33 }}"
27+
ruby-32-matrix: "${{ steps.set-matrix.outputs.ruby-32 }}"
28+
steps:
29+
- uses: actions/checkout@v4
30+
- run: bundle install
31+
- id: set-matrix
32+
run: |
33+
matrix_json=$(bundle exec rake github:generate_matrix)
34+
# Debug output
35+
echo "Generated JSON:"
36+
echo "$matrix_json"
37+
# Set the output
38+
echo "${{ matrix.engine.alias }}=$(echo "$matrix_json")" >> $GITHUB_OUTPUT
39+
- run: bundle cache
40+
- uses: actions/upload-artifact@v4
41+
with:
42+
name: bundled-dependencies-${{ github.run_id }}-${{ matrix.engine.alias }}
43+
retention-days: 1
44+
path: |
45+
Gemfile.lock
46+
vendor/
47+
test-ruby-33:
48+
name: 'ruby-3.3: ${{ matrix.task }} (${{ matrix.group }})'
49+
needs:
50+
- compute_tasks
51+
runs-on: ubuntu-22.04
52+
strategy:
53+
fail-fast: false
54+
matrix:
55+
include: "${{ fromJson(needs.compute_tasks.outputs.ruby-33-matrix) }}"
56+
container:
57+
image: ghcr.io/datadog/images-rb/engines/ruby:3.3
58+
steps:
59+
- uses: actions/checkout@v4
60+
- name: Configure Git
61+
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
62+
- uses: actions/download-artifact@v4
63+
with:
64+
name: bundled-dependencies-${{ github.run_id }}-ruby-33
65+
- run: bundle install --local
66+
- name: Test ${{ matrix.task }} with ${{ matrix.gemfile }}
67+
env:
68+
BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
69+
run: bundle install && bundle exec rake spec:${{ matrix.task }}
70+
test-ruby-32:
71+
name: 'ruby-3.2: ${{ matrix.task }} (${{ matrix.group }})'
72+
needs:
73+
- compute_tasks
74+
runs-on: ubuntu-22.04
75+
strategy:
76+
fail-fast: false
77+
matrix:
78+
include: "${{ fromJson(needs.compute_tasks.outputs.ruby-32-matrix) }}"
79+
container:
80+
image: ghcr.io/datadog/images-rb/engines/ruby:3.2
81+
steps:
82+
- uses: actions/checkout@v4
83+
- name: Configure Git
84+
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
85+
- uses: actions/download-artifact@v4
86+
with:
87+
name: bundled-dependencies-${{ github.run_id }}-ruby-32
88+
- run: bundle install --local
89+
- name: Test ${{ matrix.task }} with ${{ matrix.gemfile }}
90+
env:
91+
BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
92+
run: bundle install && bundle exec rake spec:${{ matrix.task }}

Rakefile

+15-15
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,6 @@ if Gem.loaded_specs.key? "ruby_memcheck"
2020
)
2121
end
2222

23-
RSpec::Core::RakeTask.new(:spec)
24-
25-
Dir.glob("tasks/*.rake").each { |r| import r }
26-
27-
YARD::Rake::YardocTask.new(:docs) do |t|
28-
# Options defined in `.yardopts` are read first, then merged with
29-
# options defined here.
30-
#
31-
# It's recommended to define options in `.yardopts` instead of here,
32-
# as `.yardopts` can be read by external YARD tools, like the
33-
# hot-reload YARD server `yard server --reload`.
34-
35-
t.options += ["--title", "datadog-ci #{Datadog::CI::VERSION} documentation"]
36-
end
37-
3823
# ADD NEW RUBIES HERE
3924
TEST_METADATA = {
4025
"main" => {
@@ -84,6 +69,21 @@ TEST_METADATA = {
8469
}
8570
}
8671

72+
RSpec::Core::RakeTask.new(:spec)
73+
74+
Dir.glob("tasks/*.rake").each { |r| import r }
75+
76+
YARD::Rake::YardocTask.new(:docs) do |t|
77+
# Options defined in `.yardopts` are read first, then merged with
78+
# options defined here.
79+
#
80+
# It's recommended to define options in `.yardopts` instead of here,
81+
# as `.yardopts` can be read by external YARD tools, like the
82+
# hot-reload YARD server `yard server --reload`.
83+
84+
t.options += ["--title", "datadog-ci #{Datadog::CI::VERSION} documentation"]
85+
end
86+
8787
namespace :test do
8888
task all: TEST_METADATA.map { |k, _| "test:#{k}" }
8989

tasks/appraisal_conversion.rb

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
require 'pathname'
2+
3+
# This module translates our custom mapping between appraisal and bundler.
4+
#
5+
# It cannot be included into `Appraisal` file, because it was invoked via `instance_eval`.
6+
module AppraisalConversion
7+
module_function
8+
9+
@gemfile_dir = 'gemfiles'
10+
@definition_dir = 'appraisal'
11+
12+
def to_bundle_gemfile(group)
13+
gemfile = "#{runtime_identifier}_#{group}.gemfile".tr('-', '_')
14+
path = root_path.join(gemfile_dir, gemfile)
15+
16+
if path.exist?
17+
path.to_s
18+
else
19+
raise "Gemfile not found at #{path}"
20+
end
21+
end
22+
23+
def definition
24+
path = root_path.join(@definition_dir, "#{runtime_identifier}.rb")
25+
26+
if path.exist?
27+
path.to_s
28+
else
29+
raise "Definition not found at #{path}"
30+
end
31+
end
32+
33+
def runtime_identifier
34+
major, minor, = Gem::Version.new(RUBY_ENGINE_VERSION).segments
35+
"#{RUBY_ENGINE}-#{major}.#{minor}"
36+
end
37+
38+
def gemfile_pattern
39+
root_path + gemfile_dir + "#{runtime_identifier.tr('-', '_')}_*.gemfile"
40+
end
41+
42+
def gemfile_dir
43+
@gemfile_dir
44+
end
45+
46+
def root_path
47+
Pathname.pwd
48+
end
49+
end

tasks/github.rake

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
require 'json'
2+
require "psych"
3+
require 'ostruct'
4+
require_relative 'appraisal_conversion'
5+
6+
# rubocop:disable Metrics/BlockLength
7+
namespace :github do
8+
namespace :actions do
9+
task :test_template do |t|
10+
ubuntu = "ubuntu-22.04"
11+
12+
runtimes = [
13+
"ruby:3.3",
14+
"ruby:3.2",
15+
# "ruby:3.1",
16+
# "ruby:3.0",
17+
# "ruby:2.7",
18+
# "ruby:2.6",
19+
# "ruby:2.5",
20+
# "jruby:9.4",
21+
# "jruby:9.3",
22+
# "jruby:9.2",
23+
].map do |runtime|
24+
engine, version = runtime.split(':')
25+
runtime_alias = "#{engine}-#{version.gsub('.', '')}"
26+
27+
OpenStruct.new(
28+
"engine" => engine,
29+
"version" => version,
30+
"alias" => runtime_alias,
31+
"image" => "ghcr.io/datadog/images-rb/engines/#{engine}:#{version}"
32+
)
33+
end
34+
35+
test_jobs = runtimes.map do |runtime|
36+
{
37+
"test-#{runtime.alias}" => {
38+
"name" => "#{runtime.engine}-#{runtime.version}: ${{ matrix.task }} (${{ matrix.group }})",
39+
"needs" => ["compute_tasks"],
40+
"runs-on" => ubuntu,
41+
"strategy" => {
42+
"fail-fast" => false,
43+
"matrix" => {
44+
"include" => "${{ fromJson(needs.compute_tasks.outputs.#{runtime.alias}-matrix) }}"
45+
}
46+
},
47+
"steps" => [
48+
{ "uses" => "actions/checkout@v4" },
49+
{
50+
"name" => "Configure Git",
51+
"run" => 'git config --global --add safe.directory "$GITHUB_WORKSPACE"'
52+
},
53+
{
54+
"uses" => "actions/download-artifact@v4",
55+
"with" => {
56+
"name" => "bundled-dependencies-${{ github.run_id }}-#{runtime.alias}",
57+
}
58+
},
59+
{ "run" => "bundle install --local" },
60+
{
61+
"name" => "Test ${{ matrix.task }} with ${{ matrix.gemfile }}",
62+
"env" => { "BUNDLE_GEMFILE" => "${{ matrix.gemfile }}" },
63+
"run" => "bundle install && bundle exec rake spec:${{ matrix.task }}"
64+
}
65+
]
66+
}
67+
}
68+
end
69+
70+
compute_tasks = {
71+
"runs-on" => ubuntu,
72+
"strategy" => {
73+
"fail-fast" => false,
74+
"matrix" => {
75+
"engine" => runtimes.map do |runtime|
76+
{ "name" => runtime.engine, "version" => runtime.version, "alias" => runtime.alias }
77+
end
78+
}
79+
},
80+
"container" =>{
81+
"image" => "ghcr.io/datadog/images-rb/engines/${{ matrix.engine.name }}:${{ matrix.engine.version }}"
82+
},
83+
"outputs" => runtimes.each_with_object({}) do |runtime, hash|
84+
hash["#{runtime.alias}-matrix"] = "${{ steps.set-matrix.outputs.#{runtime.alias} }}"
85+
end,
86+
"steps" => [
87+
{ "uses" => "actions/checkout@v4" },
88+
{ "run" => "bundle install" },
89+
{
90+
"id" => "set-matrix",
91+
"run" => <<~BASH
92+
matrix_json=$(bundle exec rake github:generate_matrix)
93+
# Debug output
94+
echo "Generated JSON:"
95+
echo "$matrix_json"
96+
# Set the output
97+
echo "${{ matrix.engine.alias }}=$(echo "$matrix_json")" >> $GITHUB_OUTPUT
98+
BASH
99+
},
100+
{ "run" => "bundle cache" },
101+
{
102+
"uses" => "actions/upload-artifact@v4",
103+
"with" => {
104+
"name" => "bundled-dependencies-${{ github.run_id }}-${{ matrix.engine.alias }}",
105+
"retention-days" => 1,
106+
"path" => <<~STRING
107+
Gemfile.lock
108+
vendor/
109+
STRING
110+
}
111+
},
112+
]
113+
}
114+
115+
base = {
116+
"name" => 'Test',
117+
"on" => ['push'],
118+
"concurrency" => {
119+
"group" => '${{ github.workflow }}-${{ github.ref }}',
120+
"cancel-in-progress" => '${{ github.ref != \'refs/heads/master\' }}'
121+
},
122+
"jobs" => {
123+
"compute_tasks" => compute_tasks,
124+
**test_jobs.reduce(&:merge)
125+
}
126+
}
127+
128+
# `Psych.dump` directly creates anchors, but Github Actions does not support anchors for YAML,
129+
# convert to JSON first to avoid anchors
130+
json = JSON.dump(base)
131+
yaml = Psych.safe_load(json)
132+
133+
string = +""
134+
string << <<~EOS
135+
# Please do NOT manually edit this file.
136+
# This file is generated by 'bundle exec rake #{t.name}'
137+
EOS
138+
string << Psych.dump(yaml, line_width: 120)
139+
File.binwrite(".github/workflows/test.yml", string)
140+
end
141+
end
142+
143+
task :generate_matrix do
144+
matrix = TEST_METADATA
145+
146+
ruby_version = RUBY_VERSION[0..2]
147+
major, minor, = Gem::Version.new(RUBY_ENGINE_VERSION).segments
148+
ruby_runtime = "#{RUBY_ENGINE}-#{major}.#{minor}"
149+
array = []
150+
matrix.each do |key, spec_metadata|
151+
spec_metadata.each do |group, rubies|
152+
matched = if RUBY_PLATFORM == 'java'
153+
rubies.include?("✅ #{ruby_version}") && rubies.include?('✅ jruby')
154+
else
155+
rubies.include?("✅ #{ruby_version}")
156+
end
157+
158+
if matched
159+
gemfile = AppraisalConversion.to_bundle_gemfile(group) rescue "Gemfile"
160+
161+
array << {
162+
group: group,
163+
gemfile: gemfile,
164+
task: key
165+
}
166+
end
167+
end
168+
end
169+
170+
puts JSON.dump(array)
171+
end
172+
end
173+
# rubocop:enable Metrics/BlockLength

0 commit comments

Comments
 (0)