Skip to content

Commit 613a23f

Browse files
committed
Add a workflow:
- This creates the whole dance of: 1. Run the packaging for all platforms. This basically creates the `*.gem` file with the precompiled binaries. This allow us to save time by doing everything in one go. The whole thing is then uploaded and the zip includes the gem ready to be released but also the binaries that we'll use to run the test suite agains. 2. We download the tarball, move all the compiled binaries for a platform inside the gem require paths. The test suite then runs against the compiled binaries. We also run the test suite by compiling once more, this time using the currently running ruby version. This basically allow to test the `require "#{ruby_version}/date_core.so"` as well as the `require "date_core.so"` when a user will be downloading the gem for a platform we didn't compile with. 3. We make sure `gem install` on the `.gem` works 4. We release the gems - Lot of cleanup but I'll take care of that in another PR.
1 parent 3c7da3f commit 613a23f

File tree

9 files changed

+163
-103
lines changed

9 files changed

+163
-103
lines changed

.github/actions/easy_compile/action.yml

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,76 @@ inputs:
66
description: "The working directory of the gem"
77
default: "."
88
required: false
9+
step:
10+
description: "The step to run"
11+
required: true
12+
token:
13+
description: "Not important" # TODO Remove this. I only need that for testing purposes
14+
required: false
915

1016
runs:
1117
using: "composite"
1218
steps:
13-
- name: Checkout easy compile
19+
- name: Checkout easy compile # TODO this can be removed once this tool is pusblished on RubyGems
1420
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
1521
with:
1622
path: "tmp"
1723
repository: "shopify-playground/edouard-playground"
18-
- name: Install easy compile
24+
- name: Install easy compile # TODO this can be removed once this tool is pusblished on RubyGems
1925
shell: bash
2026
run: "rake install"
2127
working-directory: "tmp"
22-
- name: Compile and test
23-
working-directory: ${{ inputs.working-directory }}
24-
shell: bash
25-
run: easy_compile
2628
- name: "Setup Rake Compiler"
29+
if: "${{ inputs.step == 'compile' }}"
2730
uses: actions/github-script@v8
2831
with:
2932
script: |
3033
const url = new URL(`file:///${process.env.GITHUB_ACTION_PATH}/dist/index.js`);
3134
const { run } = await import(url.href)
3235
await run('${{ inputs.working-directory }}')
33-
- name: Package gems with precompiled binaries
36+
- name: Package
37+
if: "${{ inputs.step == 'compile' }}"
3438
working-directory: ${{ inputs.working-directory }}
3539
shell: bash
36-
run: easy_compile clobber && easy_compile package
40+
run: easy_compile package
3741
- name: Upload artifacts
42+
if: "${{ inputs.step == 'compile' }}"
3843
uses: actions/upload-artifact@v4
3944
with:
40-
name: "package-${{ runner.os }}-${{ runner.arch }}"
41-
path: "${{ inputs.working-directory }}/pkg/*.gem"
45+
name: "stage-${{ runner.os }}-${{ runner.arch }}"
46+
path: |
47+
${{ inputs.working-directory }}/tmp/**/*.so
48+
${{ inputs.working-directory }}/tmp/**/*.bundle
49+
${{ inputs.working-directory }}/pkg/*.gem
4250
if-no-files-found: error
43-
overwrite: true
4451
retention-days: 1
52+
- name: "Download compiled binaries"
53+
if: "${{ inputs.step == 'test_cross' }}"
54+
uses: actions/download-artifact@v5
55+
with:
56+
name: "stage-${{ runner.os }}-${{ runner.arch }}"
57+
path: "${{ inputs.working-directory }}"
58+
- name: "Copy staging binary to the libdir"
59+
if: "${{ inputs.step == 'test_cross' }}"
60+
working-directory: ${{ inputs.working-directory }}
61+
shell: bash
62+
run: easy_compile copy_from_staging_to_lib
63+
- name: "Compile native"
64+
if: "${{ inputs.step == 'test_native' }}"
65+
working-directory: ${{ inputs.working-directory }}
66+
shell: bash
67+
run: easy_compile compile
68+
- name: "Execute the tests"
69+
if: "${{ startsWith(inputs.step, 'test') }}"
70+
working-directory: ${{ inputs.working-directory }}
71+
shell: bash
72+
run: bundle exec rake test # TODO This should be configurable
73+
- name: "Download gems"
74+
if: "${{ inputs.step == 'install' }}"
75+
uses: actions/download-artifact@v5
76+
with:
77+
name: "stage-${{ runner.os }}-${{ runner.arch }}"
78+
- name: "Install gems"
79+
if: "${{ inputs.step == 'install' }}"
80+
shell: bash
81+
run: gem install pkg/*.gem

.github/actions/easy_publish/action.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ inputs:
66
description: "The working directory of the gem"
77
default: "."
88
required: false
9+
token:
10+
description: "Not important" # TODO No need for this. Only for testing purposes
11+
required: false
912

1013
runs:
1114
using: "composite"
@@ -21,7 +24,11 @@ runs:
2124
working-directory: "tmp"
2225
- uses: actions/download-artifact@v5
2326
with:
24-
path: "${{ inputs.working-directory }}/pkg"
27+
artifact-ids: 4283005309,4283005567
28+
run-id: 18545927463
29+
github-token: "${{ inputs.token }}"
30+
path: "${{ inputs.working-directory }}"
31+
# path: "${{ inputs.working-directory }}/pkg"
2532
merge-multiple: true
2633
- name: "Release"
2734
uses: Edouard-chin/release-gem@ec-working-dir

.github/workflows/gem-compile.yml

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,97 @@
11
name: "Compile and test the date gem"
22
on: [push]
33
jobs:
4-
compile_and_test:
5-
name: "Complile and test the date gem"
4+
compile:
5+
timeout-minutes: 10 # TODO This should be configurable
6+
name: "Cross compile the gem on different ruby versions"
67
strategy:
78
matrix:
8-
version: ["3.4.4"]
9-
os: ["ubuntu-latest"]
9+
os: ["ubuntu-latest", "macos-latest"]
1010
runs-on: "${{ matrix.os }}"
1111
steps:
1212
- name: "Checkout code"
1313
uses: "actions/checkout@v5"
1414
- name: "Setup Ruby"
1515
uses: "ruby/setup-ruby@v1"
1616
with:
17-
ruby-version: "${{ matrix.version }}"
17+
ruby-version: "3.4.7" # TODO This should be determined dynamically.
1818
bundler-cache: true
1919
working-directory: "test/fixtures/date"
2020
- name: "Run easy compile"
2121
uses: "./.github/actions/easy_compile"
2222
with:
2323
working-directory: "test/fixtures/date"
24+
step: "compile"
25+
test:
26+
permissions: # TODO This can be removed. I just need this temporarily to download the artifact from a previous workflow
27+
actions: read
28+
contents: read
29+
timeout-minutes: 10 # TODO This should be configurable
30+
name: "Run the test suite"
31+
needs: compile
32+
strategy:
33+
matrix:
34+
os: ["ubuntu-latest", "macos-latest"]
35+
rubies: ["3.0.7", "3.1.7", "3.2.9", "3.3.9", "3.4.6"] # TODO This should be determined dynamically.
36+
type: ["cross", "native"]
37+
runs-on: "${{ matrix.os }}"
38+
steps:
39+
- name: "Checkout code"
40+
uses: "actions/checkout@v5"
41+
- name: "Setup Ruby"
42+
uses: "ruby/setup-ruby@v1"
43+
with:
44+
ruby-version: "${{ matrix.rubies }}"
45+
bundler-cache: true
46+
working-directory: "test/fixtures/date"
47+
- name: "Run easy compile"
48+
uses: "./.github/actions/easy_compile"
49+
with:
50+
working-directory: "test/fixtures/date"
51+
step: "test_${{ matrix.type }}"
52+
token: ${{ secrets.GITHUB_TOKEN }} # TODO This can be removed. Only for testing
53+
install:
54+
permissions: # TODO This can be removed. I just need this temporarily to download the artifact from a previous workflow
55+
actions: read
56+
contents: read
57+
timeout-minutes: 5
58+
name: "Verify the gem can be installed"
59+
needs: test
60+
strategy:
61+
matrix:
62+
os: ["ubuntu-latest", "macos-latest"]
63+
runs-on: "${{ matrix.os }}"
64+
steps:
65+
- name: "Checkout code" # TODO No need to checkout the codebase. Have to do it here because the relative path to the action doesn't work otherwise.
66+
uses: "actions/checkout@v5"
67+
- name: "Setup Ruby"
68+
uses: "ruby/setup-ruby@v1"
69+
with:
70+
ruby-version: "3.4.7" # TODO This needs to be determined dynamically.
71+
- name: "Run easy compile"
72+
uses: "./.github/actions/easy_compile"
73+
with:
74+
step: "install"
75+
release:
76+
permissions: # TODO This can be removed. I just need this temporarily to download the artifact from a previous workflow
77+
actions: read
78+
contents: read
79+
id-token: write
80+
timeout-minutes: 5
81+
name: "Release all gems with RubyGems"
82+
needs: install
83+
runs-on: "ubuntu-latest"
84+
steps:
85+
- name: "Checkout code" # TODO No need to checkout the codebase. Have to do it here because the relative path to the action doesn't work otherwise.
86+
uses: "actions/checkout@v5"
87+
- name: "Setup Ruby"
88+
uses: "ruby/setup-ruby@v1"
89+
with:
90+
ruby-version: "3.4.7"
91+
bundler-cache: true
92+
working-directory: "test/fixtures/date"
93+
- name: "Run easy compile"
94+
uses: "./.github/actions/easy_publish"
95+
with:
96+
working-directory: "test/fixtures/date"
97+
token: "${{ secrets.GITHUB_TOKEN }}"

Rakefile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
# frozen_string_literal: true
22

33
require "bundler/gem_tasks"
4-
require "minitest/test_task"
5-
6-
Minitest::TestTask.create
74

85
task default: :test

easy_compile.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
1212
spec.description = "Add a description laster"
1313
spec.homepage = "https://github.com"
1414
spec.license = "MIT"
15-
spec.required_ruby_version = ">= 3.2.0"
15+
spec.required_ruby_version = ">= 3.0.0"
1616

1717
spec.metadata["allowed_push_host"] = "https://rubygems.org"
1818
spec.metadata["homepage_uri"] = spec.homepage

lib/easy_compile/cli.rb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,30 @@ def self.exit_on_failure?
1515
true
1616
end
1717

18-
desc "compile_and_test", "Compile a gem's native extension based on its gemspec and run the test suite."
19-
def compile_and_test
18+
desc "compile", "Compile a gem's native extension based on its gemspec."
19+
def compile
2020
run_rake_tasks!(:compile)
2121
end
2222

23+
desc "compile_cross_rubies", "Compile a gem's native extension based on its gemspec."
24+
def compile_cross_rubies
25+
ENV["RUBY_CC_VERSION"] ||= compilation_task.ruby_cc_version
26+
27+
run_rake_tasks!(:cross, :compile)
28+
end
29+
2330
desc "package", "Package the gem and its extension"
2431
def package
2532
ENV["RUBY_CC_VERSION"] ||= compilation_task.ruby_cc_version
2633

2734
run_rake_tasks!(:cross, :native, :gem)
2835
end
2936

37+
desc "copy_from_staging_to_lib", "Copy the staging binary"
38+
def copy_from_staging_to_lib
39+
run_rake_tasks!("copy:stage:lib")
40+
end
41+
3042
desc "clean", "Cleanup compilation artifacts."
3143
def clean
3244
run_rake_tasks!(:clean)

lib/easy_compile/compilation_tasks.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
# frozen_string_literal: true
22

33
require "bundler"
4-
require "rubygems/gemspec_helpers"
54
require "rubygems/package_task"
65
require "rake/extensiontask"
76

87
module EasyCompile
98
class CompilationTasks
10-
include Gem::GemspecHelpers
11-
12-
attr_reader :gemspec, :native, :create_packaging_task
9+
attr_reader :gemspec, :native, :create_packaging_task, :extension_task
1310
attr_accessor :binary_name
1411

1512
def initialize(create_packaging_task = false, gemspec = nil)
@@ -64,7 +61,7 @@ def with_mkmf_monkey_patch
6461
def define_task(path)
6562
require File.expand_path(path)
6663

67-
Rake::ExtensionTask.new do |ext|
64+
@extension_task = Rake::ExtensionTask.new do |ext|
6865
ext.name = File.basename(binary_name)
6966
ext.config_script = File.basename(path)
7067
ext.ext_dir = File.dirname(path)
@@ -124,5 +121,9 @@ def cross_rubies
124121

125122
versions.map { |version| Gem::Version.new(version) }
126123
end
124+
125+
def find_gemspec(glob = "*.gemspec")
126+
Dir.glob(glob).sort.first
127+
end
127128
end
128129
end

lib/easy_compile/tasks/wrapper.rake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@ require_relative "../compilation_tasks"
44

55
task = EasyCompile::CompilationTasks.new(!Rake::Task.task_defined?(:package))
66
task.setup
7+
8+
task "copy:stage:lib" do
9+
version = RUBY_VERSION.match(/(\d\.\d)/)[1]
10+
path = "#{task.extension_task.lib_dir}/#{version}"
11+
12+
cp_r("tmp/#{task.extension_task.cross_platform}/stage/#{path}", path, remove_destination: true)
13+
end

test/fixtures/date/lib/dummy_date.rb

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)