rbs 4.1.1.pre.1-java → 4.1.2-java
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/.github/workflows/jruby.yml +1 -6
- data/.github/workflows/release-gems.yml +106 -35
- data/CHANGELOG.md +16 -1
- data/README.md +1 -1
- data/Rakefile +136 -101
- data/docs/release.md +125 -29
- data/lib/rbs/version.rb +1 -1
- data/wasm/README.md +33 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7f6e4569588dd9eedcb1ba5870467a07929b78d4835efd094a61c0961f4452f7
|
|
4
|
+
data.tar.gz: e276b9379a7745f1886551f618ad059e5d75fa876729815311d40c18d8779709
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 34148f72eaa920f876182110b854974b4554b5bc20589148254569b07201d083b3705330dee501c459b2241e5516a4166bd03013996647642c316f9a88506c0a
|
|
7
|
+
data.tar.gz: 2f19729a93364aeda81c447b1f232a7fbc3ad37ebd74e0a23f3d3176bbaddcf2c303c235f355d92b58be545620583b540a6ef666f8f63d5b8fa6ba40ffe4d393
|
data/.github/workflows/jruby.yml
CHANGED
|
@@ -64,12 +64,7 @@ jobs:
|
|
|
64
64
|
ruby-version: jruby
|
|
65
65
|
bundler: none
|
|
66
66
|
- name: Install runtime and test gems
|
|
67
|
-
|
|
68
|
-
# C-extension rbs gem and fails to build on JRuby. Pin rdoc below 8 until
|
|
69
|
-
# a -java rbs gem is published.
|
|
70
|
-
run: |
|
|
71
|
-
gem install prism rake rake-compiler test-unit rspec minitest json-schema pry --no-document
|
|
72
|
-
gem install rdoc -v "< 8" --no-document
|
|
67
|
+
run: gem install prism rake rake-compiler test-unit rdoc rspec minitest json-schema pry --no-document
|
|
73
68
|
# jar-dependencies resolves through the JVM, so download the Chicory/ASM
|
|
74
69
|
# jars into ~/.m2 here on JRuby (jar-dependencies is not available in the
|
|
75
70
|
# CRuby step above).
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
name: Release gems
|
|
2
2
|
|
|
3
|
-
# Builds, publishes, and announces a release. Dispatch it
|
|
4
|
-
#
|
|
5
|
-
# traces back to an immutable ref, and so the reversible step comes before the
|
|
6
|
-
# irreversible one.
|
|
3
|
+
# Builds, publishes, and announces a release. Dispatch it with the commit being
|
|
4
|
+
# released and the version that commit declares.
|
|
7
5
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
6
|
+
# Everything is built from `commit`, not from wherever the default branch happens to
|
|
7
|
+
# be when the run starts, so the release describes a state that is already immutable.
|
|
8
|
+
# `version` is the same fact stated a second time -- the run stops before anything is
|
|
9
|
+
# built unless it matches the `RBS::VERSION` of that commit, so dispatching the wrong
|
|
10
|
+
# commit, or the right one under the wrong name, is a failed run rather than a gem
|
|
11
|
+
# that has to be yanked.
|
|
12
|
+
#
|
|
13
|
+
# `dry_run` builds and checks both gems and stops before the tag, which is how the
|
|
14
|
+
# build is exercised without releasing anything.
|
|
10
15
|
#
|
|
11
16
|
# | Gem | Platform | Parser |
|
|
12
17
|
# | -------------------- | ------------- | -------------------------------- |
|
|
@@ -19,11 +24,26 @@ name: Release gems
|
|
|
19
24
|
#
|
|
20
25
|
# One job on purpose. Tagging, pushing the gems, and opening the GitHub release
|
|
21
26
|
# all belong to a single release, and keeping them in one place keeps their order
|
|
22
|
-
# readable -- the tag is created
|
|
23
|
-
# step comes before the irreversible
|
|
27
|
+
# readable -- the tag is created once both gems are known to build and run, and
|
|
28
|
+
# before anything is published, so the reversible step comes before the irreversible
|
|
29
|
+
# one.
|
|
30
|
+
#
|
|
31
|
+
# The file name is what the RubyGems trusted publisher for `rbs` is registered
|
|
32
|
+
# against, so it cannot be renamed without registering the new name first.
|
|
24
33
|
|
|
25
34
|
on:
|
|
26
35
|
workflow_dispatch:
|
|
36
|
+
inputs:
|
|
37
|
+
commit:
|
|
38
|
+
description: "Commit to release, as a full 40-character SHA"
|
|
39
|
+
required: true
|
|
40
|
+
version:
|
|
41
|
+
description: "Version to release, without the leading `v` (e.g. `4.1.2`)"
|
|
42
|
+
required: true
|
|
43
|
+
dry_run:
|
|
44
|
+
description: "Build and check the gems without tagging or publishing anything"
|
|
45
|
+
type: boolean
|
|
46
|
+
default: false
|
|
27
47
|
|
|
28
48
|
permissions:
|
|
29
49
|
contents: read
|
|
@@ -38,12 +58,60 @@ jobs:
|
|
|
38
58
|
name: release
|
|
39
59
|
runs-on: ubuntu-latest
|
|
40
60
|
permissions:
|
|
41
|
-
contents: write # publish the GitHub release
|
|
61
|
+
contents: write # push the tag, publish the GitHub release
|
|
42
62
|
id-token: write # trusted publishing to RubyGems
|
|
63
|
+
env:
|
|
64
|
+
# The inputs are read through the environment rather than interpolated into
|
|
65
|
+
# the scripts below.
|
|
66
|
+
COMMIT: ${{ inputs.commit }}
|
|
67
|
+
VERSION: ${{ inputs.version }}
|
|
68
|
+
TAG: v${{ inputs.version }}
|
|
43
69
|
steps:
|
|
44
70
|
# The gemspec takes its file list from `git ls-files`, so both gems are built
|
|
45
|
-
# from the committed state
|
|
71
|
+
# from the committed state -- of the dispatched commit, since that is what is
|
|
72
|
+
# checked out. The full history is needed to tell which branches contain it.
|
|
46
73
|
- uses: actions/checkout@v7
|
|
74
|
+
with:
|
|
75
|
+
ref: ${{ inputs.commit }}
|
|
76
|
+
fetch-depth: 0
|
|
77
|
+
|
|
78
|
+
# Before anything is installed or built: these are the two things the release
|
|
79
|
+
# is named after and built from, and a mistake in either is cheapest to catch
|
|
80
|
+
# here.
|
|
81
|
+
- name: Check the inputs
|
|
82
|
+
run: |
|
|
83
|
+
if [[ ! "$COMMIT" =~ ^[0-9a-f]{40}$ ]]; then
|
|
84
|
+
echo "::error::\`$COMMIT\` is not a full 40-character SHA. A release names one exact commit."
|
|
85
|
+
exit 1
|
|
86
|
+
fi
|
|
87
|
+
if [[ ! "$VERSION" =~ ^[0-9][0-9a-zA-Z.]*$ ]]; then
|
|
88
|
+
echo "::error::\`$VERSION\` is not a version number. Pass it without the leading \`v\`."
|
|
89
|
+
exit 1
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# A release proper is cut from the default branch, while a patch release can
|
|
93
|
+
# be cut from a release branch, so which branch the commit is on is not this
|
|
94
|
+
# workflow's business. That it is on one is: a commit no branch contains is
|
|
95
|
+
# one that nothing in the repository leads to any more.
|
|
96
|
+
git fetch --no-tags origin "+refs/heads/*:refs/remotes/origin/*"
|
|
97
|
+
branches=$(git branch --remotes --contains "$COMMIT" --format "%(refname:lstrip=3)")
|
|
98
|
+
if [ -z "$branches" ]; then
|
|
99
|
+
echo "::error::$COMMIT is not on any branch."
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
echo "Branches containing $COMMIT:"
|
|
103
|
+
printf '%s\n' "$branches"
|
|
104
|
+
|
|
105
|
+
# A tag that already exists is a version that has already been released, and
|
|
106
|
+
# pushing it would fail after the build rather than before it.
|
|
107
|
+
- name: Check that the tag does not exist
|
|
108
|
+
if: ${{ !inputs.dry_run }}
|
|
109
|
+
run: |
|
|
110
|
+
if git ls-remote --exit-code --tags origin "refs/tags/$TAG" > /dev/null; then
|
|
111
|
+
echo "::error::$TAG already exists, so $VERSION has been released."
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
47
115
|
- name: Set up Ruby
|
|
48
116
|
uses: ruby/setup-ruby@v1
|
|
49
117
|
with:
|
|
@@ -56,25 +124,16 @@ jobs:
|
|
|
56
124
|
bundle config set --local without libs:profilers
|
|
57
125
|
bundle install --jobs 4 --retry 3
|
|
58
126
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# the tag is what the release is named after, so it has to be the version the
|
|
65
|
-
# tagged commit actually declares.
|
|
66
|
-
- name: Check the tag against RBS::VERSION
|
|
67
|
-
if: github.ref_type == 'tag'
|
|
68
|
-
run: |
|
|
69
|
-
if [ "${{ github.ref_name }}" != "v${{ steps.version.outputs.version }}" ]; then
|
|
70
|
-
echo "::error::tag ${{ github.ref_name }} does not match RBS::VERSION ${{ steps.version.outputs.version }}"
|
|
71
|
-
exit 1
|
|
72
|
-
fi
|
|
127
|
+
# Fails before a minute is spent on the build, and before anything is pushed:
|
|
128
|
+
# the version has to be the one the released commit declares, and -- unless
|
|
129
|
+
# this is a `.dev.N` release -- the one CHANGELOG.md is written up for.
|
|
130
|
+
- name: Check the version and the changelog
|
|
131
|
+
run: bundle exec rake "gem:check_release[$VERSION]"
|
|
73
132
|
|
|
74
133
|
- name: Build the ruby gem
|
|
75
134
|
run: |
|
|
76
135
|
mkdir -p pkg
|
|
77
|
-
gem build rbs.gemspec -o "pkg/rbs-$
|
|
136
|
+
gem build rbs.gemspec -o "pkg/rbs-$VERSION.gem"
|
|
78
137
|
|
|
79
138
|
# `rake wasm:jruby_setup` compiles src/**/*.c to WebAssembly and copies the
|
|
80
139
|
# result to lib/rbs/wasm/, where the gemspec picks it up. clang runs as a
|
|
@@ -91,7 +150,7 @@ jobs:
|
|
|
91
150
|
- name: Build the java gem
|
|
92
151
|
env:
|
|
93
152
|
RBS_PLATFORM: java
|
|
94
|
-
run: gem build rbs.gemspec -o "pkg/rbs-$
|
|
153
|
+
run: gem build rbs.gemspec -o "pkg/rbs-$VERSION-java.gem"
|
|
95
154
|
|
|
96
155
|
# `git ls-files` vouches for everything else, but rbs_parser.wasm is a build
|
|
97
156
|
# artifact, so the java gem is the one that can come out quietly wrong.
|
|
@@ -108,8 +167,7 @@ jobs:
|
|
|
108
167
|
raise "the java gem must not declare an extension" unless java_gem.extensions.empty?
|
|
109
168
|
|
|
110
169
|
[ruby_gem, java_gem].each { puts "#{_1.full_name}: #{_1.files.size} files" }
|
|
111
|
-
' "pkg/rbs-$
|
|
112
|
-
"pkg/rbs-${{ steps.version.outputs.version }}-java.gem"
|
|
170
|
+
' "pkg/rbs-$VERSION.gem" "pkg/rbs-$VERSION-java.gem"
|
|
113
171
|
|
|
114
172
|
# The checks above cannot tell whether rbs_parser.wasm actually runs. Install
|
|
115
173
|
# the gem the way a user would -- jar-dependencies fetches Chicory and ASM
|
|
@@ -122,7 +180,7 @@ jobs:
|
|
|
122
180
|
bundler: none
|
|
123
181
|
- name: Check the java gem on JRuby
|
|
124
182
|
run: |
|
|
125
|
-
gem install "pkg/rbs-$
|
|
183
|
+
gem install "pkg/rbs-$VERSION-java.gem"
|
|
126
184
|
ruby -e '
|
|
127
185
|
require "rbs"
|
|
128
186
|
_, _, decls = RBS::Parser.parse_signature("class Foo end")
|
|
@@ -138,27 +196,40 @@ jobs:
|
|
|
138
196
|
bundler: none
|
|
139
197
|
|
|
140
198
|
# Uploaded before publishing, so a failed push still leaves the gems behind.
|
|
199
|
+
# This is also where a dry run ends.
|
|
141
200
|
- uses: actions/upload-artifact@v7
|
|
142
201
|
with:
|
|
143
202
|
name: gems
|
|
144
203
|
path: pkg/*.gem
|
|
145
204
|
if-no-files-found: error
|
|
146
205
|
|
|
147
|
-
# Everything below runs only for a release
|
|
206
|
+
# Everything below runs only for a real release.
|
|
207
|
+
|
|
208
|
+
# The tag comes after the gems are known to build and run, and before anything
|
|
209
|
+
# is published: a tag can be deleted, while a version pushed to RubyGems can
|
|
210
|
+
# only be yanked. What it names was decided by the checkout rather than by the
|
|
211
|
+
# tagging, so nothing rests on it being created first.
|
|
212
|
+
- name: Tag the release
|
|
213
|
+
if: ${{ !inputs.dry_run }}
|
|
214
|
+
run: |
|
|
215
|
+
git config user.name "github-actions[bot]"
|
|
216
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
217
|
+
bundle exec rake gem:tag
|
|
218
|
+
|
|
148
219
|
- name: Configure RubyGems credentials
|
|
149
|
-
if:
|
|
220
|
+
if: ${{ !inputs.dry_run }}
|
|
150
221
|
# No floating major tag on this action, so the exact release is pinned.
|
|
151
222
|
uses: rubygems/configure-rubygems-credentials@v2.1.0
|
|
152
223
|
|
|
153
224
|
- name: Push the gems
|
|
154
|
-
if:
|
|
225
|
+
if: ${{ !inputs.dry_run }}
|
|
155
226
|
run: |
|
|
156
|
-
gem push "pkg/rbs-$
|
|
157
|
-
gem push "pkg/rbs-$
|
|
227
|
+
gem push "pkg/rbs-$VERSION.gem"
|
|
228
|
+
gem push "pkg/rbs-$VERSION-java.gem"
|
|
158
229
|
|
|
159
230
|
# Last, so that a failed push never announces a release that has no gems.
|
|
160
231
|
- name: Publish the GitHub release
|
|
161
|
-
if:
|
|
232
|
+
if: ${{ !inputs.dry_run }}
|
|
162
233
|
env:
|
|
163
234
|
GH_TOKEN: ${{ github.token }}
|
|
164
235
|
run: bundle exec rake gem:gh_release
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
## 4.1.
|
|
3
|
+
## 4.1.2 (2026-08-03)
|
|
4
|
+
|
|
5
|
+
### Miscellaneous
|
|
6
|
+
|
|
7
|
+
* Keep GC disabled during GC_test#test_stress_and_stress= ([#3061](https://github.com/ruby/rbs/pull/3061))
|
|
8
|
+
* Fix GC_test#test_enable leaving GC disabled for the rest of the suite ([#3059](https://github.com/ruby/rbs/pull/3059))
|
|
9
|
+
|
|
10
|
+
## 4.1.1 (2026-07-30)
|
|
4
11
|
|
|
5
12
|
### Library changes
|
|
6
13
|
|
|
@@ -99,6 +106,14 @@ This release also introduces `RBS::Rewriter`, an API to edit RBS source text whi
|
|
|
99
106
|
* ci: skip Gemfile.lock BUNDLED WITH on ruby-head ([#2952](https://github.com/ruby/rbs/pull/2952))
|
|
100
107
|
* Remove `logger` from sig dependencies ([#2904](https://github.com/ruby/rbs/pull/2904))
|
|
101
108
|
|
|
109
|
+
## 4.0.3 (2026-06-18)
|
|
110
|
+
|
|
111
|
+
### Miscellaneous
|
|
112
|
+
|
|
113
|
+
* Fix Ruby CI failure with compressed `Zlib::GzipReader` test fixtures. ([#3005](https://github.com/ruby/rbs/pull/3005))
|
|
114
|
+
* Fix flaky `DirSingletonTest#test_fchdir` and `DirSingletonTest#test_for_fd` under aggressive GC. ([#3005](https://github.com/ruby/rbs/pull/3005))
|
|
115
|
+
* Fix Ruby head CI failure caused by the lockfile-pinned Bundler version. ([#3005](https://github.com/ruby/rbs/pull/3005))
|
|
116
|
+
|
|
102
117
|
## 4.0.2 (2026-03-25)
|
|
103
118
|
|
|
104
119
|
### Library changes
|
data/README.md
CHANGED
|
@@ -196,7 +196,7 @@ Here is a list of some places you can talk with active maintainers.
|
|
|
196
196
|
|
|
197
197
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
198
198
|
|
|
199
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
199
|
+
To install this gem onto your local machine, run `bundle exec rake install`. Releases are cut by the `Release gems` workflow rather than from a working copy -- see [docs/release.md](docs/release.md).
|
|
200
200
|
|
|
201
201
|
### C Code Formatting
|
|
202
202
|
|
data/Rakefile
CHANGED
|
@@ -438,73 +438,6 @@ task :test_generate_stdlib do
|
|
|
438
438
|
sh "ruby -c /tmp/Thread_Mutex_test.rb"
|
|
439
439
|
end
|
|
440
440
|
|
|
441
|
-
Rake::Task[:release].enhance do
|
|
442
|
-
Rake::Task[:"release:note"].invoke
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
namespace :release do
|
|
446
|
-
desc "Explain the post-release steps automatically"
|
|
447
|
-
task :note do
|
|
448
|
-
version = Gem::Version.new(RBS::VERSION)
|
|
449
|
-
major, minor, patch, *_ = RBS::VERSION.split(".")
|
|
450
|
-
major = major.to_i
|
|
451
|
-
minor = minor.to_i
|
|
452
|
-
patch = patch.to_i
|
|
453
|
-
|
|
454
|
-
puts "🎉🎉🎉🎉 Congratulations for **#{version}** release! 🎉🎉🎉🎉"
|
|
455
|
-
puts
|
|
456
|
-
puts "There are a few things left to complete the release. 💪"
|
|
457
|
-
puts
|
|
458
|
-
|
|
459
|
-
if patch == 0 || version.prerelease?
|
|
460
|
-
puts "* [ ] Update release note: https://github.com/ruby/rbs/wiki/Release-Note-#{major}.#{minor}"
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
if patch == 0 && !version.prerelease?
|
|
464
|
-
puts "* [ ] Delete `RBS XYZ is the latest version of...` from release note: https://github.com/ruby/rbs/wiki/Release-Note-#{major}.#{minor}"
|
|
465
|
-
end
|
|
466
|
-
|
|
467
|
-
puts "* [ ] Publish a release at GitHub"
|
|
468
|
-
puts "* [ ] Make some announcements on Twitter/Mustdon/Slack/???"
|
|
469
|
-
|
|
470
|
-
puts
|
|
471
|
-
puts
|
|
472
|
-
|
|
473
|
-
puts "✏️ Making a draft release on GitHub..."
|
|
474
|
-
|
|
475
|
-
content = File.read(File.join(__dir__, "CHANGELOG.md"))
|
|
476
|
-
changelog = content.scan(/^## \d.*?(?=^## \d)/m)[0]
|
|
477
|
-
changelog = changelog.sub(/^.*\n^.*\n/, "").rstrip
|
|
478
|
-
|
|
479
|
-
notes = <<NOTES
|
|
480
|
-
[Release note](https://github.com/ruby/rbs/wiki/Release-Note-#{major}.#{minor})
|
|
481
|
-
|
|
482
|
-
#{changelog}
|
|
483
|
-
NOTES
|
|
484
|
-
|
|
485
|
-
command = [
|
|
486
|
-
"gh",
|
|
487
|
-
"release",
|
|
488
|
-
"create",
|
|
489
|
-
"--draft",
|
|
490
|
-
"v#{RBS::VERSION}",
|
|
491
|
-
"--title=#{RBS::VERSION}",
|
|
492
|
-
"--notes=#{notes}"
|
|
493
|
-
]
|
|
494
|
-
|
|
495
|
-
if version.prerelease?
|
|
496
|
-
command << "--prerelease"
|
|
497
|
-
end
|
|
498
|
-
|
|
499
|
-
require "open3"
|
|
500
|
-
output, status = Open3.capture2(*command)
|
|
501
|
-
if status.success?
|
|
502
|
-
puts " >> Done! Open #{output.chomp} and publish the release!"
|
|
503
|
-
end
|
|
504
|
-
end
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
|
|
508
441
|
# Pull requests with one of these labels are omitted from the changelog.
|
|
509
442
|
CHANGELOG_SKIP_LABELS = ["skip-changelog"]
|
|
510
443
|
|
|
@@ -594,20 +527,54 @@ def changelog_commits(from, paths: [])
|
|
|
594
527
|
output.lines.map(&:chomp).reject(&:empty?)
|
|
595
528
|
end
|
|
596
529
|
|
|
597
|
-
#
|
|
530
|
+
# What `git cherry-pick -x` appends to the message of the commit it creates.
|
|
531
|
+
CHERRY_PICK_ORIGIN = /^\(cherry picked from commit ([0-9a-f]{40})\)$/
|
|
532
|
+
|
|
533
|
+
# Maps the commits that record where they were cherry-picked from to that commit.
|
|
598
534
|
#
|
|
599
|
-
#
|
|
535
|
+
# A backport is a cherry-pick, so on a release branch it is the recorded origin, not the commit
|
|
536
|
+
# itself, that leads to the pull request the change was written and reviewed in. Without this a
|
|
537
|
+
# backported change is attributed to the pull request that carried the backport, which says
|
|
538
|
+
# nothing about the change and is the same for every commit it brought over.
|
|
600
539
|
#
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
540
|
+
# A commit backported twice -- the development line, then a release branch -- carries one line
|
|
541
|
+
# per hop, appended in order, so the first one is where the change started.
|
|
542
|
+
#
|
|
543
|
+
def changelog_origins(commits)
|
|
544
|
+
return {} if commits.empty?
|
|
545
|
+
|
|
546
|
+
require "open3"
|
|
547
|
+
|
|
548
|
+
# `--no-walk` prints these commits and nothing else. NUL delimiters keep a commit message --
|
|
549
|
+
# which can contain anything, including what this format looks like -- from being read as the
|
|
550
|
+
# format itself.
|
|
551
|
+
output, status = Open3.capture2("git", "log", "--no-walk", "--format=%H%x00%B%x00", *commits, binmode: true)
|
|
552
|
+
raise status.inspect unless status.success?
|
|
553
|
+
|
|
554
|
+
# Commit messages are UTF-8, while the default external encoding follows the locale. Without
|
|
555
|
+
# this, splitting a message that is not ASCII fails under `LANG=C`, as in GitHub Actions.
|
|
556
|
+
output.force_encoding(Encoding::UTF_8)
|
|
604
557
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
558
|
+
output.split("\0").each_slice(2).each_with_object({}) do |(commit, message), origins|
|
|
559
|
+
commit = commit.to_s.strip
|
|
560
|
+
next if commit.empty?
|
|
561
|
+
|
|
562
|
+
origin = message.to_s[CHERRY_PICK_ORIGIN, 1] or next
|
|
563
|
+
origins[commit] = origin
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
# Asks GitHub which pull requests each commit came from, so that any merge strategy -- merge
|
|
568
|
+
# commit, squash, or rebase -- is handled without parsing commit messages.
|
|
569
|
+
#
|
|
570
|
+
# Returns `{ oid => [pull request, ...] }`, with an empty array for the commits GitHub has no
|
|
571
|
+
# merged pull request for, including the ones it does not know at all.
|
|
572
|
+
#
|
|
573
|
+
def changelog_associated_pull_requests(oids)
|
|
574
|
+
oids.uniq.each_slice(50).each_with_object({}) do |slice, found|
|
|
575
|
+
aliases = slice.map.with_index do |oid, index|
|
|
609
576
|
<<~GRAPHQL
|
|
610
|
-
c#{index}: object(oid: "#{
|
|
577
|
+
c#{index}: object(oid: "#{oid}") {
|
|
611
578
|
... on Commit {
|
|
612
579
|
associatedPullRequests(first: 10) {
|
|
613
580
|
nodes {
|
|
@@ -620,18 +587,44 @@ def changelog_pull_requests(commits, skip_labels: CHANGELOG_SKIP_LABELS)
|
|
|
620
587
|
GRAPHQL
|
|
621
588
|
end
|
|
622
589
|
|
|
623
|
-
changelog_graphql(aliases.join("\n"))
|
|
624
|
-
next unless commit
|
|
590
|
+
response = changelog_graphql(aliases.join("\n"))
|
|
625
591
|
|
|
626
|
-
|
|
627
|
-
|
|
592
|
+
slice.each_with_index do |oid, index|
|
|
593
|
+
nodes = response.dig(:"c#{index}", :associatedPullRequests, :nodes) || []
|
|
628
594
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
595
|
+
found[oid] = nodes.select { |pr| pr[:merged] }.map do |pr|
|
|
596
|
+
{ number: pr[:number], title: pr[:title], url: pr[:url], labels: pr.dig(:labels, :nodes).map { |label| label[:name] } }
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
# Finds the pull requests the commits came from, keeping the order of `commits`.
|
|
603
|
+
#
|
|
604
|
+
# Returns the pull requests for the changelog and the ones omitted by `skip_labels`.
|
|
605
|
+
#
|
|
606
|
+
def changelog_pull_requests(commits, skip_labels: CHANGELOG_SKIP_LABELS)
|
|
607
|
+
origins = changelog_origins(commits)
|
|
608
|
+
found = changelog_associated_pull_requests(commits.map { |commit| origins[commit] || commit })
|
|
609
|
+
|
|
610
|
+
# An origin that leads nowhere -- a commit cherry-picked from a fork, or one that went to the
|
|
611
|
+
# default branch without a pull request -- falls back to the commit in this history, which is
|
|
612
|
+
# at least the backport that brought it here.
|
|
613
|
+
fallbacks = commits.select { |commit| origins[commit] && found.fetch(origins[commit], []).empty? }
|
|
614
|
+
found.update(changelog_associated_pull_requests(fallbacks)) unless fallbacks.empty?
|
|
615
|
+
|
|
616
|
+
pull_requests = {}
|
|
617
|
+
skipped = {}
|
|
618
|
+
|
|
619
|
+
commits.each do |commit|
|
|
620
|
+
prs = found.fetch(origins[commit] || commit, [])
|
|
621
|
+
prs = found.fetch(commit, []) if prs.empty?
|
|
622
|
+
|
|
623
|
+
prs.each do |pr|
|
|
624
|
+
if (pr[:labels] & skip_labels).empty?
|
|
625
|
+
pull_requests[pr[:number]] ||= pr
|
|
626
|
+
else
|
|
627
|
+
skipped[pr[:number]] ||= pr
|
|
635
628
|
end
|
|
636
629
|
end
|
|
637
630
|
end
|
|
@@ -779,6 +772,60 @@ namespace :gem do
|
|
|
779
772
|
end
|
|
780
773
|
end
|
|
781
774
|
|
|
775
|
+
# There are three kinds of release: `X.Y.Z`, `X.Y.Z.pre.N`, and `X.Y.Z.dev.N`. The
|
|
776
|
+
# `.dev.N` ones are cut from the development line for people who need a specific
|
|
777
|
+
# change early; they are not written up in the changelog, so there are no notes to
|
|
778
|
+
# publish and nothing worth announcing.
|
|
779
|
+
def dev_release?(version)
|
|
780
|
+
Gem::Version.new(version).segments.include?("dev")
|
|
781
|
+
end
|
|
782
|
+
|
|
783
|
+
# The body of the topmost section of CHANGELOG.md, which is the release being
|
|
784
|
+
# prepared, minus its own heading.
|
|
785
|
+
#
|
|
786
|
+
# The encoding is explicit because the default external encoding follows the
|
|
787
|
+
# locale, and the changelog is not ASCII.
|
|
788
|
+
#
|
|
789
|
+
def changelog_section(version)
|
|
790
|
+
content = File.read(File.join(__dir__, "CHANGELOG.md"), encoding: Encoding::UTF_8)
|
|
791
|
+
section = content.scan(/^## \d.*?(?=^## \d)/m)[0] or raise "🚨 Cannot find a release section in CHANGELOG.md"
|
|
792
|
+
heading, _, body = section.partition("\n")
|
|
793
|
+
heading.include?(version) or raise "🚨 CHANGELOG.md starts with `#{heading.strip}`, which is not #{version}"
|
|
794
|
+
body.strip
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
desc "Check that the working tree is ready to be released as the given version"
|
|
798
|
+
task :check_release, [:version] do |_task, args|
|
|
799
|
+
version = args[:version] or raise "🚨 Pass the version being released: `rake 'gem:check_release[4.1.2]'`"
|
|
800
|
+
Gem::Version.correct?(version) or raise "🚨 `#{version}` is not a version number."
|
|
801
|
+
|
|
802
|
+
# The version being released and the version the commit declares are stated
|
|
803
|
+
# separately -- one by whoever starts the release, one by the commit itself --
|
|
804
|
+
# so that releasing the wrong commit, or releasing the right one under the wrong
|
|
805
|
+
# name, fails here rather than on RubyGems.
|
|
806
|
+
version == RBS::VERSION or
|
|
807
|
+
raise "🚨 Releasing #{version}, but this commit declares `RBS::VERSION = #{RBS::VERSION.inspect}`."
|
|
808
|
+
|
|
809
|
+
if dev_release?(version)
|
|
810
|
+
puts "✅ #{version} is the version of this commit. It is a dev release, so CHANGELOG.md is not checked."
|
|
811
|
+
else
|
|
812
|
+
changelog_section(version)
|
|
813
|
+
puts "✅ #{version} is the version of this commit, and CHANGELOG.md documents it."
|
|
814
|
+
end
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
desc "Create and push the `vX.Y.Z` tag for RBS::VERSION"
|
|
818
|
+
task :tag do
|
|
819
|
+
tag = "v#{RBS::VERSION}"
|
|
820
|
+
|
|
821
|
+
# Annotated, so that the tag carries its own author and date rather than
|
|
822
|
+
# borrowing the tagged commit's.
|
|
823
|
+
sh "git", "tag", "--annotate", "--message", "RBS #{RBS::VERSION}", tag
|
|
824
|
+
sh "git", "push", "origin", tag
|
|
825
|
+
|
|
826
|
+
puts "🏷️ Pushed #{tag}."
|
|
827
|
+
end
|
|
828
|
+
|
|
782
829
|
desc "Publish the GitHub release for RBS::VERSION, unless it is a `.dev.` version"
|
|
783
830
|
task :gh_release do
|
|
784
831
|
require "open3"
|
|
@@ -787,11 +834,7 @@ namespace :gem do
|
|
|
787
834
|
major, minor, *_ = RBS::VERSION.split(".")
|
|
788
835
|
tag = "v#{RBS::VERSION}"
|
|
789
836
|
|
|
790
|
-
|
|
791
|
-
# The `.dev.N` ones are cut from the development line for people who need a
|
|
792
|
-
# specific change early; they are not written up in the changelog, so there are
|
|
793
|
-
# no notes to publish and nothing worth announcing.
|
|
794
|
-
if version.segments.include?("dev")
|
|
837
|
+
if dev_release?(RBS::VERSION)
|
|
795
838
|
puts "⏭️ #{RBS::VERSION} is a dev release, so there is no GitHub release to publish."
|
|
796
839
|
next
|
|
797
840
|
end
|
|
@@ -801,18 +844,10 @@ namespace :gem do
|
|
|
801
844
|
_, status = Open3.capture2("git", "rev-parse", "--verify", "--quiet", "#{tag}^{commit}")
|
|
802
845
|
raise "🚨 No such tag: `#{tag}`. Tag the release before creating the GitHub release." unless status.success?
|
|
803
846
|
|
|
804
|
-
# The topmost section of the changelog is this release, minus its own heading.
|
|
805
|
-
# The encoding is explicit because the default external encoding follows the
|
|
806
|
-
# locale, and the changelog is not ASCII.
|
|
807
|
-
content = File.read(File.join(__dir__, "CHANGELOG.md"), encoding: Encoding::UTF_8)
|
|
808
|
-
section = content.scan(/^## \d.*?(?=^## \d)/m)[0] or raise "🚨 Cannot find a release section in CHANGELOG.md"
|
|
809
|
-
heading, _, body = section.partition("\n")
|
|
810
|
-
heading.include?(RBS::VERSION) or raise "🚨 CHANGELOG.md starts with `#{heading.strip}`, which is not #{RBS::VERSION}"
|
|
811
|
-
|
|
812
847
|
notes = <<~NOTES
|
|
813
848
|
[Release note](https://github.com/ruby/rbs/wiki/Release-Note-#{major}.#{minor})
|
|
814
849
|
|
|
815
|
-
#{
|
|
850
|
+
#{changelog_section(RBS::VERSION)}
|
|
816
851
|
NOTES
|
|
817
852
|
|
|
818
853
|
# Published rather than drafted: the notes are the changelog section that was
|
data/docs/release.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Releasing RBS
|
|
2
2
|
|
|
3
|
-
A release is a pull request
|
|
4
|
-
|
|
5
|
-
gems` workflow, so nothing has to be built or pushed from a laptop.
|
|
3
|
+
A release is a pull request and one workflow run. Everything that leaves the
|
|
4
|
+
repository — the tag, both gems, and the GitHub release — is produced by the
|
|
5
|
+
`Release gems` workflow, so nothing has to be built or pushed from a laptop.
|
|
6
6
|
|
|
7
7
|
Each release ships **two gems**:
|
|
8
8
|
|
|
@@ -36,6 +36,14 @@ is what lets you dispatch the workflow.
|
|
|
36
36
|
|
|
37
37
|
## Steps
|
|
38
38
|
|
|
39
|
+
The release pull request in step 1 is merged by a person who has reviewed it. Its merge commit is
|
|
40
|
+
what step 2 dispatches, tags, and pushes to RubyGems, and none of that can be taken back — so
|
|
41
|
+
prepare that pull request and stop there, rather than merging it and carrying on to step 2.
|
|
42
|
+
|
|
43
|
+
The bump that starts a new minor is the only other pull request that sets `RBS::VERSION`. It
|
|
44
|
+
publishes nothing and another bump undoes it, so one opened on an explicit request can go through
|
|
45
|
+
on its own.
|
|
46
|
+
|
|
39
47
|
### 1. Prepare the release
|
|
40
48
|
|
|
41
49
|
Open a pull request that carries everything the release needs:
|
|
@@ -97,26 +105,29 @@ on a small release. Two things scale with the size of the release:
|
|
|
97
105
|
The date is the day the gem is released, matching the `vX.Y.Z` tag — not the day this pull request
|
|
98
106
|
is opened. Fix it up before step 2 if the pull request sat for a few days.
|
|
99
107
|
|
|
100
|
-
### 2.
|
|
108
|
+
### 2. Run the `Release gems` workflow
|
|
101
109
|
|
|
102
|
-
Once the pull request is merged,
|
|
110
|
+
Once the pull request is merged, dispatch
|
|
111
|
+
[`release-gems.yml`](../.github/workflows/release-gems.yml) from the Actions tab with two inputs:
|
|
103
112
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
```
|
|
113
|
+
| Input | Value |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| `commit` | The full 40-character SHA of the merge commit, taken from the merged pull request |
|
|
116
|
+
| `version` | `X.Y.Z`, without the leading `v` |
|
|
109
117
|
|
|
110
|
-
The
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
The ref selector picks which copy of the workflow file runs, not what gets released — leave it on
|
|
119
|
+
`master`. Everything is built from `commit`, so the run is unaffected by whatever lands on `master`
|
|
120
|
+
in the meantime, and a patch release cut from a release branch is dispatched the same way as any
|
|
121
|
+
other: the workflow does not care which branch the commit is on.
|
|
113
122
|
|
|
114
|
-
|
|
123
|
+
The two inputs say the same thing twice, once as a commit and once as a name, and the run stops
|
|
124
|
+
before anything is built unless they agree with each other and with the repository:
|
|
115
125
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
126
|
+
- `commit` has to be a full SHA that some branch contains,
|
|
127
|
+
- `version` has to be the `RBS::VERSION` that commit declares,
|
|
128
|
+
- CHANGELOG.md has to start with a section for `version` (skipped for `.dev.N`, which is not
|
|
129
|
+
written up),
|
|
130
|
+
- `vX.Y.Z` must not exist yet.
|
|
120
131
|
|
|
121
132
|
It then:
|
|
122
133
|
|
|
@@ -127,25 +138,110 @@ It then:
|
|
|
127
138
|
- installs the `java` gem on JRuby and parses with it, so the WebAssembly runtime is exercised
|
|
128
139
|
before anything is published,
|
|
129
140
|
- uploads both gems as an artifact,
|
|
130
|
-
-
|
|
141
|
+
- tags `commit` as `vX.Y.Z` and pushes the tag,
|
|
142
|
+
- pushes both gems to RubyGems through trusted publishing,
|
|
131
143
|
- publishes the GitHub release with the notes from CHANGELOG.md, skipping this last step for
|
|
132
144
|
`.dev.N` versions.
|
|
133
145
|
|
|
134
|
-
|
|
135
|
-
|
|
146
|
+
The tag is created once both gems are known to build and run, and before anything is published: a
|
|
147
|
+
tag can be deleted, while a version pushed to RubyGems can only be yanked.
|
|
148
|
+
|
|
149
|
+
Checking the `dry_run` box runs everything up to the artifact and stops — no tag, no gems pushed,
|
|
150
|
+
no release — which is how the build is exercised without releasing. `version` still has to match
|
|
151
|
+
the commit, so a dry run is also how a release is rehearsed before it is cut.
|
|
152
|
+
|
|
153
|
+
## The version on `master`
|
|
154
|
+
|
|
155
|
+
`RBS::VERSION` on `master` is read one of two ways, told apart by how the version ends:
|
|
156
|
+
|
|
157
|
+
| On `master` | Means |
|
|
158
|
+
| --- | --- |
|
|
159
|
+
| `X.Y.0.dev` — a bare `.dev` | `X.Y.0` is being developed |
|
|
160
|
+
| A complete version — `X.Y.Z`, `X.Y.Z.pre.N`, `X.Y.Z.dev.N` | The version *after* the one named is being developed |
|
|
161
|
+
|
|
162
|
+
So `4.1.1` on `master` is not a claim that `master` is 4.1.1. It says 4.1.1 has shipped and what
|
|
163
|
+
comes after it is being worked on. `4.1.2.dev.1` says the same thing about itself: that release is
|
|
164
|
+
out, and the line continues towards 4.1.2.
|
|
165
|
+
|
|
166
|
+
Both become true the moment the release is tagged, so **nothing has to be done to `master` after a
|
|
167
|
+
release**. `4.0.1` was followed by `4.0.2` with no version change in between, and `4.1.2.dev.1` is
|
|
168
|
+
what `master` carries today.
|
|
169
|
+
|
|
170
|
+
The bare `X.Y.0.dev` is the exception because it is the one version that names a target rather than
|
|
171
|
+
a predecessor: a new minor is developed towards `X.Y.0` for a long time, before it is known whether
|
|
172
|
+
the next thing to ship is `X.Y.0.pre.1` or `X.Y.0` itself. Setting it is the only version change
|
|
173
|
+
that has to be made deliberately.
|
|
174
|
+
|
|
175
|
+
`rake gem:changelog` reads `RBS::VERSION` too, to decide where the next changelog starts — but the
|
|
176
|
+
version is set to the one being released before the changelog is generated, so it sees that rather
|
|
177
|
+
than whatever `master` was carrying.
|
|
136
178
|
|
|
137
|
-
|
|
179
|
+
## Starting a new minor
|
|
180
|
+
|
|
181
|
+
`master` is the development line of one minor at a time. Moving it from `X.Y` to `X.(Y+1)` is not
|
|
182
|
+
part of any one release — it is the decision that the `X.Y` line is done, taken whenever that
|
|
183
|
+
becomes true — and it is the one moment the version on `master` is changed by hand. Two changes, in
|
|
184
|
+
opposite places:
|
|
185
|
+
|
|
186
|
+
1. **Branch the line being left behind**, from the last `master` commit that belongs to it:
|
|
187
|
+
|
|
188
|
+
```console
|
|
189
|
+
$ git switch --create aaa-X.Y.x <that commit>
|
|
190
|
+
$ git push -u origin aaa-X.Y.x
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Branch from the commit *before* the bump below, so the branch keeps the version its line was
|
|
194
|
+
released under. Patch releases of `X.Y` are cut from here from now on, with their changes
|
|
195
|
+
cherry-picked from `master` — see [Backports](#backports). The `aaa-` prefix carries no meaning
|
|
196
|
+
beyond sorting the release branches to the top of the branch list.
|
|
197
|
+
|
|
198
|
+
2. **Bump `master`** to `X.(Y+1).0.dev`, in a pull request with `Gemfile.lock` regenerated and
|
|
199
|
+
labeled `skip-changelog` like the release pull request itself. `4.1` was started exactly this
|
|
200
|
+
way: `aaa-4.0.x` was branched at the commit before `Start 4.1 development`, which set
|
|
201
|
+
`RBS::VERSION` to `4.1.0.dev`.
|
|
202
|
+
|
|
203
|
+
Two loose ends that are easy to forget:
|
|
204
|
+
|
|
205
|
+
- **The release note of the new line.** `rake gem:gh_release` links every published release to
|
|
206
|
+
`https://github.com/ruby/rbs/wiki/Release-Note-X.Y`, built from the version number without
|
|
207
|
+
checking that the page is there. Nothing has to be written when the line starts — the page comes
|
|
208
|
+
together as the first release proper of the line comes into view — but it does have to exist by
|
|
209
|
+
the time that release is published, or its notes link to an empty page.
|
|
210
|
+
- **Release branches that are done.** A branch is worth keeping only while its line might still
|
|
211
|
+
get a patch. The ones that exist do not cover every line that ever had one — `3.8.1` shipped and
|
|
212
|
+
there is no `aaa-3.8.x` — so this is housekeeping rather than a rule, but starting a new minor is
|
|
213
|
+
the natural moment to look at the bottom of the branch list and delete what has been superseded.
|
|
214
|
+
|
|
215
|
+
## Backports
|
|
216
|
+
|
|
217
|
+
A patch release is cut from a release branch (`aaa-X.Y.x`), and what it carries beyond the previous
|
|
218
|
+
release is cherry-picked from the development line. Cherry-pick with `-x`:
|
|
219
|
+
|
|
220
|
+
```console
|
|
221
|
+
$ git cherry-pick -x <commit>
|
|
222
|
+
```
|
|
138
223
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
224
|
+
`-x` records the commit the change was copied from, and that recorded line is what `rake
|
|
225
|
+
gem:changelog` follows to reach the pull request the change was written and reviewed in. Without
|
|
226
|
+
it, the only pull request a backported commit is associated with is the one that carried the
|
|
227
|
+
backport, which says nothing about the change and is the same for every commit it brought over —
|
|
228
|
+
that is why the 4.0.3 changelog credits its three entries to the same pull request.
|
|
144
229
|
|
|
145
230
|
## Notes
|
|
146
231
|
|
|
147
232
|
- Prereleases (`X.Y.Z.pre.N`) are only installed with `gem install rbs --pre`;
|
|
148
233
|
a plain `gem install rbs` is unaffected. On JRuby, `gem install rbs [--pre]`
|
|
149
234
|
resolves to the `-java` gem automatically.
|
|
150
|
-
-
|
|
151
|
-
`
|
|
235
|
+
- The WASI SDK version is pinned in `wasm.yml`, `jruby.yml`, `release-gems.yml`, and
|
|
236
|
+
`Dockerfile.jruby`, each carrying its own copy. Keep them in sync when bumping. The
|
|
237
|
+
Chicory/ASM versions are not duplicated: they are the `jar` requirements in
|
|
238
|
+
`rbs.gemspec`, which is where the workflow, `Dockerfile.jruby` and `gem install` all
|
|
239
|
+
read them from.
|
|
240
|
+
- `rake 'gem:check_release[X.Y.Z]'` and `rake gem:tag` are what the workflow runs to
|
|
241
|
+
check the release and to create the tag. Both work locally, which is the fallback
|
|
242
|
+
if the tag ever has to be created by hand.
|
|
243
|
+
- Those two tasks and `rake gem:gh_release` come from the Rakefile of the commit
|
|
244
|
+
being released, not from the branch the workflow was dispatched from. Releasing
|
|
245
|
+
from a release branch (`aaa-X.Y.x`) therefore needs the release tooling on that
|
|
246
|
+
branch as well; without it the run fails on the missing task, before publishing
|
|
247
|
+
anything.
|
data/lib/rbs/version.rb
CHANGED
data/wasm/README.md
CHANGED
|
@@ -27,6 +27,39 @@ $ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 (run on JRub
|
|
|
27
27
|
|
|
28
28
|
The compiled `rbs_parser.wasm` is a build artifact and is not checked in.
|
|
29
29
|
|
|
30
|
+
The WASI SDK is needed for the *build*, not for running the result — the host clang already
|
|
31
|
+
knows the `wasm32` target, but there is no wasm32 libc on a normal machine, so it picks up the
|
|
32
|
+
host headers and fails on the first `#include`. That is what the SDK supplies, along with the
|
|
33
|
+
builtins the link step needs.
|
|
34
|
+
|
|
35
|
+
## Running the suite on JRuby
|
|
36
|
+
|
|
37
|
+
[`Dockerfile.jruby`](../Dockerfile.jruby) builds an image that has everything this needs, so no
|
|
38
|
+
JRuby, JDK or WASI SDK has to be installed to work on the JRuby side:
|
|
39
|
+
|
|
40
|
+
```console
|
|
41
|
+
$ docker build -f Dockerfile.jruby -t rbs-jruby .
|
|
42
|
+
$ docker run --rm rbs-jruby # run the test suite
|
|
43
|
+
$ docker run --rm -e RBS_PLATFORM=java rbs-jruby \
|
|
44
|
+
gem build rbs.gemspec # build the -java gem
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Two things in it are not obvious:
|
|
48
|
+
|
|
49
|
+
- `build-essential` is for prism, which builds `libprism.so` and loads it through FFI on JRuby
|
|
50
|
+
rather than as an MRI C extension. It needs `cc` and `make`.
|
|
51
|
+
- Bundler is skipped. The development `Gemfile` pulls in CRuby-only C extensions (bigdecimal,
|
|
52
|
+
stackprof, …) that cannot build on JRuby, so the few gems the suite needs are installed
|
|
53
|
+
directly, in the same set as [`jruby.yml`](../.github/workflows/jruby.yml).
|
|
54
|
+
|
|
55
|
+
The image compiles `rbs_parser.wasm` itself, which is why it carries the WASI SDK. That is not
|
|
56
|
+
the only arrangement: the build needs the SDK but not JRuby, and running the suite needs JRuby
|
|
57
|
+
but not the SDK, so `jruby.yml` splits them instead — it compiles the module on CRuby and then
|
|
58
|
+
switches engines to test against the result.
|
|
59
|
+
|
|
60
|
+
`rake wasm:install_jars` is the step that has to be on JRuby either way: it resolves the `jar`
|
|
61
|
+
requirements from `rbs.gemspec` through the JVM.
|
|
62
|
+
|
|
30
63
|
## Exported functions
|
|
31
64
|
|
|
32
65
|
The module is built as a "reactor": it has no `main`, and the host calls
|