diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml
index 3b28040c33adfb..1a84cfe390616f 100644
--- a/.github/workflows/annocheck.yml
+++ b/.github/workflows/annocheck.yml
@@ -73,7 +73,7 @@ jobs:
builddir: build
makeup: true
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.1'
bundler: none
diff --git a/.github/workflows/auto_review_pr.yml b/.github/workflows/auto_review_pr.yml
index 5a27e76b6434cf..6308b392ad7462 100644
--- a/.github/workflows/auto_review_pr.yml
+++ b/.github/workflows/auto_review_pr.yml
@@ -29,7 +29,7 @@ jobs:
with:
persist-credentials: false
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.4'
bundler: none
diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml
index 7f0613487e5fd5..23fa7aae3f2732 100644
--- a/.github/workflows/baseruby.yml
+++ b/.github/workflows/baseruby.yml
@@ -48,7 +48,7 @@ jobs:
- ruby-3.3
steps:
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml
index 6119bd5b58784e..fa5e0441c6182a 100644
--- a/.github/workflows/bundled_gems.yml
+++ b/.github/workflows/bundled_gems.yml
@@ -38,7 +38,7 @@ jobs:
with:
token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: 4.0
diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml
index 93fc2abe4d2e55..0d41a7ed981a70 100644
--- a/.github/workflows/check_dependencies.yml
+++ b/.github/workflows/check_dependencies.yml
@@ -42,7 +42,7 @@ jobs:
- uses: ./.github/actions/setup/directories
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.1'
bundler: none
diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
index bc7e36467cf2e9..29333088133d0e 100644
--- a/.github/workflows/check_misc.yml
+++ b/.github/workflows/check_misc.yml
@@ -23,7 +23,7 @@ jobs:
token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: head
diff --git a/.github/workflows/check_sast.yml b/.github/workflows/check_sast.yml
index 9bd011e0d8b3fa..7939a831e51848 100644
--- a/.github/workflows/check_sast.yml
+++ b/.github/workflows/check_sast.yml
@@ -78,14 +78,14 @@ jobs:
persist-credentials: false
- name: Initialize CodeQL
- uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
+ uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
languages: ${{ matrix.language }}
build-mode: none
config-file: .github/codeql/codeql-config.yml
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
+ uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
category: '/language:${{ matrix.language }}'
upload: False
@@ -126,7 +126,7 @@ jobs:
continue-on-error: true
- name: Upload SARIF
- uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
+ uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
sarif_file: sarif-results/${{ matrix.language }}.sarif
continue-on-error: true
diff --git a/.github/workflows/modgc.yml b/.github/workflows/modgc.yml
index 577369dc7628dc..a274b1727ecee3 100644
--- a/.github/workflows/modgc.yml
+++ b/.github/workflows/modgc.yml
@@ -62,7 +62,7 @@ jobs:
uses: ./.github/actions/setup/ubuntu
if: ${{ contains(matrix.os, 'ubuntu') }}
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.1'
bundler: none
diff --git a/.github/workflows/parse_y.yml b/.github/workflows/parse_y.yml
index 333a7a5ef9daa8..2dbbf4146687b0 100644
--- a/.github/workflows/parse_y.yml
+++ b/.github/workflows/parse_y.yml
@@ -59,7 +59,7 @@ jobs:
- uses: ./.github/actions/setup/ubuntu
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.1'
bundler: none
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index d2de7420e84977..9a8a05038762a9 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -22,7 +22,7 @@ jobs:
with:
persist-credentials: false
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: 3.3.4
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index cab229c8ef82f9..fb6d140e77f023 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -73,6 +73,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
+ uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
sarif_file: results.sarif
diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml
index fde3ffe7632240..7ddf5e02ac67dc 100644
--- a/.github/workflows/spec_guards.yml
+++ b/.github/workflows/spec_guards.yml
@@ -49,7 +49,7 @@ jobs:
with:
persist-credentials: false
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
diff --git a/.github/workflows/sync_default_gems.yml b/.github/workflows/sync_default_gems.yml
index 7bc3dff11a0eaa..72b77b6a42f642 100644
--- a/.github/workflows/sync_default_gems.yml
+++ b/.github/workflows/sync_default_gems.yml
@@ -39,7 +39,7 @@ jobs:
with:
token: ${{ github.repository == 'ruby/ruby' && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.4'
bundler: none
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index f87fcfb2592838..9bed54562d2d1b 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -70,7 +70,7 @@ jobs:
with:
arch: ${{ matrix.arch }}
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.1'
bundler: none
diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml
index 82a272f6e08038..a54e93693e84b9 100644
--- a/.github/workflows/wasm.yml
+++ b/.github/workflows/wasm.yml
@@ -99,7 +99,7 @@ jobs:
run: |
echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.1'
bundler: none
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 7017af7b1fd0a0..88ee91c518a3e6 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -59,7 +59,7 @@ jobs:
- run: md build
working-directory:
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
# windows-11-arm has only 3.4.1, 3.4.2, 3.4.3, head
ruby-version: ${{ !endsWith(matrix.os, 'arm') && '3.1' || '3.4' }}
diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml
index 1908eccbb308fa..04a009dd6fa89f 100644
--- a/.github/workflows/yjit-ubuntu.yml
+++ b/.github/workflows/yjit-ubuntu.yml
@@ -133,7 +133,7 @@ jobs:
- uses: ./.github/actions/setup/ubuntu
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.1'
bundler: none
diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml
index e64de62c052815..f6ed57353a7f0a 100644
--- a/.github/workflows/zjit-macos.yml
+++ b/.github/workflows/zjit-macos.yml
@@ -93,7 +93,7 @@ jobs:
rustup install ${{ matrix.rust_version }} --profile minimal
rustup default ${{ matrix.rust_version }}
- - uses: taiki-e/install-action@eea29cff9a2b68892c0845ae3e4f45fc47ee9354 # v2.75.13
+ - uses: taiki-e/install-action@5939f3337e40968c39aa70f5ecb1417a92fb25a0 # v2.75.15
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-check' }}
diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml
index dd486677ef49e7..4ad98b514b6937 100644
--- a/.github/workflows/zjit-ubuntu.yml
+++ b/.github/workflows/zjit-ubuntu.yml
@@ -114,12 +114,12 @@ jobs:
- uses: ./.github/actions/setup/ubuntu
- - uses: ruby/setup-ruby@4c56a21280b36d862b5fc31348f463d60bdc55d5 # v1.301.0
+ - uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
with:
ruby-version: '3.1'
bundler: none
- - uses: taiki-e/install-action@eea29cff9a2b68892c0845ae3e4f45fc47ee9354 # v2.75.13
+ - uses: taiki-e/install-action@5939f3337e40968c39aa70f5ecb1417a92fb25a0 # v2.75.15
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-check' }}
diff --git a/NEWS.md b/NEWS.md
index ad755e2e54592b..0c1efe7c969a54 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -70,6 +70,7 @@ releases.
* RubyGems 4.1.0.dev
* bundler 4.1.0.dev
* erb 6.0.3
+ * 6.0.1 to [v6.0.2][erb-v6.0.2], [v6.0.3][erb-v6.0.3]
* json 2.19.3
* 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2], [v2.19.3][json-v2.19.3]
* openssl 4.0.1
@@ -175,6 +176,8 @@ A lot of work has gone into making Ractors more stable, performant, and usable.
[prism-v1.8.1]: https://github.com/ruby/prism/releases/tag/v1.8.1
[zlib-v3.2.3]: https://github.com/ruby/zlib/releases/tag/v3.2.3
[pstore-v0.2.1]: https://github.com/ruby/pstore/releases/tag/v0.2.1
+[erb-v6.0.2]: https://github.com/ruby/erb/releases/tag/v6.0.2
+[erb-v6.0.3]: https://github.com/ruby/erb/releases/tag/v6.0.3
[json-v2.18.1]: https://github.com/ruby/json/releases/tag/v2.18.1
[json-v2.19.0]: https://github.com/ruby/json/releases/tag/v2.19.0
[json-v2.19.1]: https://github.com/ruby/json/releases/tag/v2.19.1
diff --git a/doc/syntax/calling_methods.rdoc b/doc/syntax/calling_methods.rdoc
index 76babcc3dcd969..a24c5fbf1f5ad9 100644
--- a/doc/syntax/calling_methods.rdoc
+++ b/doc/syntax/calling_methods.rdoc
@@ -425,7 +425,7 @@ as keyword arguments:
name = Name.new('Jane Doe')
p(**name)
- # Prints: {name: "Jane", last: "Doe"}
+ # Prints: {first: "Jane", last: "Doe"}
Unlike * operator, ** raises an error when used on an
object that doesn't respond to #to_hash. The one exception is
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index c705f9eac0c712..fabb308043c9c4 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -22,6 +22,12 @@ Gem::Specification.new do |spec|
spec.metadata["changelog_uri"] = "<%= config[:changelog_uri] %>"
<%- end -%>
+ # Uncomment the line below to require MFA for gem pushes.
+ # This helps protect your gem from supply chain attacks by ensuring
+ # no one can publish a new version without multi-factor authentication.
+ # See: https://guides.rubygems.org/mfa-requirement-opt-in/
+ # spec.metadata["rubygems_mfa_required"] = "true"
+
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
gemspec = File.basename(__FILE__)
diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index 5df3b58202791c..f00aa276c463d2 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -650,6 +650,15 @@ def create_temporary_dir(dir)
to match(/example\.com/)
end
+ it "includes a commented-out rubygems_mfa_required metadata hint" do
+ bundle "gem #{gem_name}"
+
+ gemspec_contents = bundled_app("#{gem_name}/#{gem_name}.gemspec").read
+
+ expect(gemspec_contents).to include('# spec.metadata["rubygems_mfa_required"] = "true"')
+ expect(gemspec_contents).to include("https://guides.rubygems.org/mfa-requirement-opt-in/")
+ end
+
it "sets a minimum ruby version" do
bundle "gem #{gem_name}"
diff --git a/test/json/json_ryu_fallback_test.rb b/test/json/json_ryu_fallback_test.rb
index 2262a6f5947540..152de7e360dc6e 100644
--- a/test/json/json_ryu_fallback_test.rb
+++ b/test/json/json_ryu_fallback_test.rb
@@ -174,10 +174,10 @@ def test_large_exponent_numbers
assert_equal Float::INFINITY, JSON.parse("1e4294967295")
assert_equal Float::INFINITY, JSON.parse("1e4294967297")
- assert_equal -Float::INFINITY, JSON.parse("-1e4294967296")
- assert_equal -0.0, JSON.parse("-1e-4294967296")
- assert_equal -0.0, JSON.parse("-99999999999999999e-4294967296")
- assert_equal -Float::INFINITY, JSON.parse("-1e4294967295")
- assert_equal -Float::INFINITY, JSON.parse("-1e4294967297")
+ assert_equal(-Float::INFINITY, JSON.parse("-1e4294967296"))
+ assert_equal(-0.0, JSON.parse("-1e-4294967296"))
+ assert_equal(-0.0, JSON.parse("-99999999999999999e-4294967296"))
+ assert_equal(-Float::INFINITY, JSON.parse("-1e4294967295"))
+ assert_equal(-Float::INFINITY, JSON.parse("-1e4294967297"))
end
end
diff --git a/tool/auto_review_pr.rb b/tool/auto_review_pr.rb
index a8f64fab9d1f79..38adf9fdb7fe42 100755
--- a/tool/auto_review_pr.rb
+++ b/tool/auto_review_pr.rb
@@ -38,6 +38,9 @@ class AutoReviewPR
UPSTREAM_COMMENT_PREFIX = 'The following files are maintained in the following upstream repositories:'
UPSTREAM_COMMENT_SUFFIX = 'Please file a pull request to the above instead. Thank you!'
+ REDMINE_TICKET_PATTERN = /\[(Bug|Feature|Misc)\s*#(\d+)\]/
+ REDMINE_COMMENT_PREFIX = 'This pull request references the following Redmine tickets:'
+
FORK_COMMENT_PREFIX = 'It looks like this pull request was filed from a branch in ruby/ruby.'
FORK_COMMENT_BODY = <<~COMMENT
#{FORK_COMMENT_PREFIX}
@@ -57,8 +60,10 @@ def initialize(client)
def review(pr_number)
existing_comments = fetch_existing_comments(pr_number)
- review_non_fork_branch(pr_number, existing_comments)
+ pr = @client.get("/repos/#{REPO}/pulls/#{pr_number}")
+ review_non_fork_branch(pr_number, pr, existing_comments)
review_upstream_repos(pr_number, existing_comments)
+ review_redmine_links(pr_number, pr, existing_comments)
end
private
@@ -78,13 +83,12 @@ def post_comment(pr_number, comment)
end
# Suggest re-filing from a fork if the PR branch is in ruby/ruby itself
- def review_non_fork_branch(pr_number, existing_comments)
+ def review_non_fork_branch(pr_number, pr, existing_comments)
if already_commented?(existing_comments, FORK_COMMENT_PREFIX)
puts "Skipped: The PR ##{pr_number} already has a fork branch comment."
return
end
- pr = @client.get("/repos/#{REPO}/pulls/#{pr_number}")
head_repo = pr.dig(:head, :repo, :full_name)
if head_repo != REPO
puts "Skipped: The PR ##{pr_number} is already from a fork (#{head_repo})."
@@ -120,6 +124,32 @@ def review_upstream_repos(pr_number, existing_comments)
post_comment(pr_number, format_upstream_comment(upstream_repos))
end
+ def review_redmine_links(pr_number, pr, existing_comments)
+ if already_commented?(existing_comments, REDMINE_COMMENT_PREFIX)
+ puts "Skipped: The PR ##{pr_number} already has a Redmine links comment."
+ return
+ end
+
+ text = "#{pr[:title]}\n#{pr[:body]}"
+
+ tickets = text.scan(REDMINE_TICKET_PATTERN).uniq
+ tickets.reject! { |_, number| text.include?("https://bugs.ruby-lang.org/issues/#{number}") }
+ if tickets.empty?
+ puts "Skipped: The PR ##{pr_number} doesn't reference any Redmine tickets."
+ return
+ end
+
+ post_comment(pr_number, format_redmine_comment(tickets))
+ end
+
+ def format_redmine_comment(tickets)
+ comment = +"#{REDMINE_COMMENT_PREFIX}\n\n"
+ tickets.each do |type, number|
+ comment << "* [#{type} ##{number}](https://bugs.ruby-lang.org/issues/#{number})\n"
+ end
+ comment
+ end
+
def format_upstream_comment(upstream_repos)
comment = +''
comment << "#{UPSTREAM_COMMENT_PREFIX}\n\n"