summaryrefslogtreecommitdiff
path: root/.github/workflows
diff options
context:
space:
mode:
Diffstat (limited to '.github/workflows')
-rw-r--r--.github/workflows/annocheck.yml110
-rw-r--r--.github/workflows/auto_request_review.yml20
-rw-r--r--.github/workflows/auto_review_pr.yml33
-rw-r--r--.github/workflows/baseruby.yml74
-rw-r--r--.github/workflows/bundled_gems.yml190
-rw-r--r--.github/workflows/check_dependencies.yml59
-rw-r--r--.github/workflows/check_misc.yml127
-rw-r--r--.github/workflows/codeql-analysis.yml121
-rw-r--r--.github/workflows/compilers.yml335
-rw-r--r--.github/workflows/cygwin.yml71
-rw-r--r--.github/workflows/default_gems_list.yml99
-rw-r--r--.github/workflows/dependabot_automerge.yml32
-rw-r--r--.github/workflows/labeler.yml12
-rw-r--r--.github/workflows/macos.yml202
-rw-r--r--.github/workflows/mingw.yml243
-rw-r--r--.github/workflows/modgc.yml176
-rw-r--r--.github/workflows/parse_y.yml100
-rw-r--r--.github/workflows/post_push.yml85
-rw-r--r--.github/workflows/pr-playground.yml127
-rw-r--r--.github/workflows/publish.yml107
-rw-r--r--.github/workflows/release.yml18
-rw-r--r--.github/workflows/rust-warnings.yml60
-rw-r--r--.github/workflows/scorecards.yml78
-rw-r--r--.github/workflows/spec_guards.yml67
-rw-r--r--.github/workflows/sync_default_gems.yml77
-rw-r--r--.github/workflows/ubuntu.yml269
-rw-r--r--.github/workflows/wasm.yml179
-rw-r--r--.github/workflows/windows.yml201
-rw-r--r--.github/workflows/wsl.yml70
-rw-r--r--.github/workflows/yjit-macos.yml198
-rw-r--r--.github/workflows/yjit-ubuntu.yml240
-rw-r--r--.github/workflows/zjit-macos.yml214
-rw-r--r--.github/workflows/zjit-ubuntu.yml267
33 files changed, 4261 insertions, 0 deletions
diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml
new file mode 100644
index 0000000000..899d601aef
--- /dev/null
+++ b/.github/workflows/annocheck.yml
@@ -0,0 +1,110 @@
+name: Annocheck
+
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ compile:
+ name: test-annocheck
+
+ runs-on: ubuntu-latest
+
+ container:
+ image: ghcr.io/ruby/ruby-ci-image:gcc-11
+ options: --user root
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ env:
+ CONFIGURE_TTY: never
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUBY_DEBUG: ci rgengc
+ RUBY_TESTOPTS: >-
+ -q
+ --color=always
+ --tty=no
+ # FIXME: Drop skipping options
+ # https://bugs.ruby-lang.org/issues/18061
+ # https://sourceware.org/annobin/annobin.html/Test-pie.html
+ TEST_ANNOCHECK_OPTS: '--skip-pie --skip-gaps'
+
+ steps:
+ - run: id
+ working-directory:
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+
+ # Minimal flags to pass the check.
+ # -g0 disables backtraces when SEGV. Do not set that.
+ - name: Run configure
+ run: >
+ ../src/configure -C
+ --enable-debug-env
+ --disable-install-doc
+ --with-ext=-test-/cxxanyargs,+
+ --without-valgrind
+ --without-jemalloc
+ --without-gmp
+ --with-gcc="gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes"
+ --enable-shared
+ debugflags=-ggdb3
+ optflags=-O2
+ LDFLAGS=-Wl,-z,now
+
+ - run: make showflags
+
+ - run: make
+
+ - run: make test-annocheck
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/auto_request_review.yml b/.github/workflows/auto_request_review.yml
new file mode 100644
index 0000000000..207315a084
--- /dev/null
+++ b/.github/workflows/auto_request_review.yml
@@ -0,0 +1,20 @@
+name: Auto Request Review
+on:
+ pull_request_target:
+ types: [opened, ready_for_review, reopened]
+ branches: [master]
+
+permissions:
+ contents: read
+
+jobs:
+ auto-request-review:
+ name: Auto Request Review
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'ruby/ruby' && github.base_ref == 'master' }}
+ steps:
+ - name: Request review based on files changes and/or groups the author belongs to
+ uses: necojackarc/auto-request-review@e89da1a8cd7c8c16d9de9c6e763290b6b0e3d424 # v0.13.0
+ with:
+ # scope: public_repo
+ token: ${{ secrets.MATZBOT_AUTO_REQUEST_REVIEW_TOKEN }}
diff --git a/.github/workflows/auto_review_pr.yml b/.github/workflows/auto_review_pr.yml
new file mode 100644
index 0000000000..ad0e63ba12
--- /dev/null
+++ b/.github/workflows/auto_review_pr.yml
@@ -0,0 +1,33 @@
+name: Auto Review PR
+on:
+ pull_request_target:
+ types: [opened, ready_for_review, reopened]
+ branches: [master]
+
+permissions:
+ contents: read
+
+jobs:
+ auto-review-pr:
+ name: Auto Review PR
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'ruby/ruby' && github.base_ref == 'master' }}
+
+ permissions:
+ pull-requests: write
+ contents: read
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6.0.1
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.4'
+ bundler: none
+
+ - name: Auto Review PR
+ run: ruby tool/auto_review_pr.rb "$GITHUB_PR_NUMBER"
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml
new file mode 100644
index 0000000000..d3e734f885
--- /dev/null
+++ b/.github/workflows/baseruby.yml
@@ -0,0 +1,74 @@
+name: BASERUBY Check
+
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ baseruby:
+ name: BASERUBY
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ strategy:
+ matrix:
+ ruby:
+ - ruby-3.1
+ - ruby-3.2
+ - ruby-3.3
+
+ steps:
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler: none
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ makeup: true
+
+ - run: ./configure --disable-install-doc
+
+ - run: make all
+
+ - run: make test
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.ruby }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml
new file mode 100644
index 0000000000..59f64e8312
--- /dev/null
+++ b/.github/workflows/bundled_gems.yml
@@ -0,0 +1,190 @@
+name: bundled_gems
+
+env:
+ UPDATE_ENABLED: true
+
+on:
+ push:
+ branches: ['master']
+ paths:
+ - '.github/workflows/bundled_gems.yml'
+ - 'gems/bundled_gems'
+ pull_request:
+ branches: ['master']
+ paths:
+ - '.github/workflows/bundled_gems.yml'
+ - 'gems/bundled_gems'
+ merge_group:
+ schedule:
+ - cron: '45 6 * * *'
+ workflow_dispatch:
+
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
+
+jobs:
+ update:
+ permissions:
+ contents: write # for Git to git push
+
+ if: ${{ github.event_name != 'schedule' || github.repository == 'ruby/ruby' }}
+
+ name: update ${{ github.workflow }}
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN
+ checkout: '' # false (ref: https://github.com/actions/runner/issues/2238)
+
+ - name: Set ENV
+ run: |
+ echo "TODAY=$(date +%F)" >> $GITHUB_ENV
+
+ - name: Download previous gems list
+ run: |
+ mkdir -p .downloaded-cache
+ for data in bundled_gems.json default_gems.json; do
+ ln -s .downloaded-cache/$data .
+ curl -O -R -z ./$data https://stdgems.org/$data
+ done
+
+ - name: Update bundled gems list
+ id: bundled_gems
+ run: |
+ ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems >> $GITHUB_OUTPUT
+ if: ${{ env.UPDATE_ENABLED == 'true' }}
+
+ - name: Update spec/bundler/support/builders.rb
+ run: |
+ #!ruby
+ rake_version = File.read("gems/bundled_gems")[/^rake\s+(\S+)/, 1]
+ print ARGF.read.sub(/^ *def rake_version\s*\K".*?"/) {rake_version.dump}
+ shell: ruby -i~ {0} spec/bundler/support/builders.rb
+ if: ${{ env.UPDATE_ENABLED == 'true' }}
+
+ - name: Maintain updated gems list in NEWS
+ run: |
+ ruby tool/update-NEWS-gemlist.rb bundled
+ if: ${{ env.UPDATE_ENABLED == 'true' }}
+
+ - name: Check diffs
+ id: diff
+ run: |
+ news= gems=
+ git diff --color --no-ext-diff --ignore-submodules --exit-code -- NEWS.md ||
+ news=true
+ git diff --color --no-ext-diff --ignore-submodules --exit-code -- gems/bundled_gems ||
+ gems=true
+ git add -- NEWS.md gems/bundled_gems
+ git add -- spec/bundler/support/builders.rb
+ echo news=$news >> $GITHUB_OUTPUT
+ echo gems=$gems >> $GITHUB_OUTPUT
+ echo update=${news:-$gems} >> $GITHUB_OUTPUT
+
+ - name: Commit
+ id: commit
+ run: |
+ git pull --ff-only origin ${GITHUB_REF#refs/heads/}
+ message="Update bundled gems list"
+ if [ -z "${gems}" ]; then
+ git commit --message="[DOC] ${message} at ${GITHUB_SHA:0:30}"
+ else
+ git commit --message="${message} as of ${TODAY}"
+ fi
+ env:
+ TODAY: ${{ steps.bundled_gems.outputs.latest_date || env.TODAY }}
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ gems: ${{ steps.diff.outputs.gems }}
+ if: ${{ steps.diff.outputs.update }}
+
+ - name: Development revision of bundled gems
+ run: |
+ #!ruby
+ file = "gems/bundled_gems"
+
+ SECONDS_IN_DAY = 86400
+ today = Time.new("#{ENV['TODAY']}Z")
+ if !(december = today.month == 12)
+ days = 30
+ elsif (days = 26 - today.day).positive?
+ days += 4
+ else
+ puts "::info:: just after released"
+ exit
+ end
+
+ since = "#{today.year-1}-12-26"
+ ref = ENV['GITHUB_REF']
+ puts "::group::\e[94mfetching \e[1m#{file}\e[22m since \e[1m#{since}\e[22m from \e[1m#{ref}\e[m"
+ system(*%W[git fetch --shallow-since=#{since} --no-tags origin #{ref}], exception: true)
+ puts "::endgroup::"
+
+ puts "\e[94mchecking development version bundled gems older than \e[1m#{days}\e[22m days\e[m"
+ limit = today.to_i - days * SECONDS_IN_DAY
+ old = 0
+ IO.popen(%W"git blame --line-porcelain -- #{file}") do |blame|
+ while head = blame.gets("\n\t") and s = blame.gets
+ next unless (gem = s.split(/\s+|#.*/)).size > 3
+ time = head[/^committer-time \K\d+/].to_i
+ next if (d = limit - time) <= 0
+ d /= SECONDS_IN_DAY
+ line = head[/\A\h+ \d+ \K\d+/].to_i
+ level = if d < days; 'warning'; else old += 1; 'error'; end
+ d += days
+ puts "::#{level} file=#{file},line=#{line},title=Older than #{d} days::#{gem[0]} #{gem[3]}"
+ end
+ end
+ abort "::error title=Too long-standing gems::The release comes soon." if december and old.nonzero?
+ shell: ruby {0}
+ env:
+ file: ${{ steps.logs.outputs.file }}
+ days: ${{ steps.logs.outputs.days }}
+
+ - name: Install libraries
+ uses: ./.github/actions/setup/ubuntu
+ if: ${{ steps.diff.outputs.gems }}
+
+ - name: Build
+ run: |
+ ./autogen.sh
+ ./configure -C --disable-install-doc
+ make
+ if: ${{ steps.diff.outputs.gems }}
+
+ - name: Prepare bundled gems
+ run: |
+ make -s prepare-gems
+ if: ${{ steps.diff.outputs.gems }}
+
+ - name: Test bundled gems
+ run: |
+ make -s test-bundled-gems
+ timeout-minutes: 30
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ if: ${{ steps.diff.outputs.gems }}
+
+ - name: Push
+ run: |
+ git push origin ${GITHUB_REF#refs/heads/}
+ if: >-
+ ${{
+ github.repository == 'ruby/ruby' &&
+ !startsWith(github.event_name, 'pull') &&
+ steps.commit.outcome == 'success'
+ }}
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml
new file mode 100644
index 0000000000..c5dec65e48
--- /dev/null
+++ b/.github/workflows/check_dependencies.yml
@@ -0,0 +1,59 @@
+name: Check Dependencies
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ update-deps:
+ name: Dependency checks
+
+ strategy:
+ matrix:
+ os: [ubuntu-latest]
+ fail-fast: true
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ./.github/actions/setup/ubuntu
+ if: ${{ contains(matrix.os, 'ubuntu') }}
+
+ - uses: ./.github/actions/setup/macos
+ if: ${{ contains(matrix.os, 'macos') }}
+
+ - uses: ./.github/actions/setup/directories
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+
+ - name: Run configure
+ run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g'
+
+ - run: make fix-depends
+
+ - run: git diff --no-ext-diff --ignore-submodules --exit-code
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.os }} / Dependencies need to update
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
new file mode 100644
index 0000000000..2a2bd1df53
--- /dev/null
+++ b/.github/workflows/check_misc.yml
@@ -0,0 +1,127 @@
+name: Misc
+on: [push, pull_request, merge_group]
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ checks:
+ name: Miscellaneous checks
+
+ permissions:
+ contents: write # for Git to git push
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ makeup: true
+ # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN
+ checkout: '' # false (ref: https://github.com/actions/runner/issues/2238)
+
+ - name: Check for code styles
+ run: |
+ set -x
+ ruby tool/auto-style.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA"
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.pull_request.base.sha }}
+ GITHUB_NEW_SHA: ${{ github.event.pull_request.merge_commit_sha }}
+ # Skip 'push' events because post_push.yml fixes them on push
+ if: ${{ github.repository == 'ruby/ruby' && startsWith(github.event_name, 'pull') }}
+
+ - name: Check for bash specific substitution in configure.ac
+ run: |
+ git grep -n '\${[A-Za-z_0-9]*/' -- configure.ac && exit 1 || :
+
+ - name: Check for header macros
+ run: |
+ fail=
+ for header in ruby/*.h; do
+ git grep -l -F -e $header -e HAVE_`echo $header | tr a-z./ A-Z__` -- . > /dev/null && continue
+ fail=1
+ echo $header
+ done
+ exit $fail
+ working-directory: include
+
+ - id: now
+ run: |
+ date +"mon=%-m"%n"day=%-d" >> $GITHUB_OUTPUT
+ env:
+ TZ: Tokyo/Asia
+
+ - id: deprecation
+ run: |
+ eval $(sed -n 's/^#define RUBY_API_VERSION_\(MAJOR\|MINOR\) /\1=/p' include/ruby/version.h)
+ if git --no-pager grep --color -o 'rb_warn_deprecated_to_remove_at('$MAJOR'\.'$MINOR',.*' -- '*.c' >&2; then
+ false
+ else
+ true
+ fi
+ continue-on-error: ${{ steps.now.outputs.mon < 12 }}
+
+ - name: Check if to generate documents
+ id: rdoc
+ run: |
+ set -- $(sed 's/#.*//;/^rdoc /!d' gems/bundled_gems)
+ { echo version=$2; echo ref=$4; } >> $GITHUB_OUTPUT
+ echo RDOC='ruby -W0 --disable-gems tool/rdoc-srcdir -q' >> $GITHUB_ENV
+
+ - name: Checkout rdoc
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ repository: ruby/rdoc
+ ref: ${{ steps.rdoc.outputs.ref }}
+ path: .bundle/gems/rdoc-${{ steps.rdoc.outputs.version }}
+ if: ${{ steps.rdoc.outputs.ref != '' }}
+
+ - name: Generate rdoc
+ run: |
+ set -x
+ gempath=$(ruby -e 'print Gem.user_dir, "/bin"')
+ PATH=$gempath:$PATH
+ gem install --user bundler
+ bundle config --local path vendor/bundle
+ bundle install --jobs 4
+ bundle exec rake generate
+ working-directory: .bundle/gems/rdoc-${{ steps.rdoc.outputs.version }}
+ if: ${{ steps.rdoc.outputs.ref != '' }}
+
+ - name: Core docs coverage
+ run: |
+ $RDOC -C -x ^ext -x ^lib .
+
+ - name: Generate docs
+ id: docs
+ run: |
+ $RDOC --op html .
+ echo htmlout=ruby-html-${GITHUB_SHA:0:10} >> $GITHUB_OUTPUT
+ # Generate only when document commit/PR
+ if: >-
+ ${{false
+ || contains(github.event.head_commit.message, '[ruby/rdoc]')
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ }}
+
+ - name: Upload docs
+ uses: actions/upload-artifact@v6.0.0
+ with:
+ path: html
+ name: ${{ steps.docs.outputs.htmlout }}
+ if: ${{ steps.docs.outcome == 'success' }}
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000000..a92c93b476
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,121 @@
+name: 'CodeQL'
+
+on:
+ push:
+ branches: ['master']
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ schedule:
+ - cron: '0 12 * * *'
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read # for github/codeql-action/init to get workflow details
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/autobuild to send a status report
+ # CodeQL fails to run pull requests from dependabot due to missing write access to upload results.
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ env:
+ enable_install_doc: no
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: cpp
+ - language: ruby
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - name: Install libraries
+ if: ${{ contains(matrix.os, 'macos') }}
+ uses: ./.github/actions/setup/macos
+
+ - name: Install libraries
+ if : ${{ matrix.os == 'ubuntu-latest' }}
+ uses: ./.github/actions/setup/ubuntu
+
+ - uses: ./.github/actions/setup/directories
+
+ - name: Remove an obsolete rubygems vendored file
+ if: ${{ matrix.os == 'ubuntu-latest' }}
+ run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
+ with:
+ languages: ${{ matrix.language }}
+ trap-caching: false
+ debug: true
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
+ with:
+ category: '/language:${{ matrix.language }}'
+ upload: False
+ output: sarif-results
+
+ - name: filter-sarif
+ uses: advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d # v1.0.1
+ with:
+ patterns: |
+ +**/*.rb
+ -lib/uri/mailto.rb:rb/overly-large-range
+ -lib/uri/rfc3986_parser.rb:rb/overly-large-range
+ -lib/bundler/vendor/uri/lib/uri/mailto.rb:rb/overly-large-range
+ -lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb:rb/overly-large-range
+ -test/ruby/test_io.rb:rb/non-constant-kernel-open
+ -test/open-uri/test_open-uri.rb:rb/non-constant-kernel-open
+ -test/open-uri/test_ssl.rb:rb/non-constant-kernel-open
+ -spec/ruby/core/io/binread_spec.rb:rb/non-constant-kernel-open
+ -spec/ruby/core/io/readlines_spec.rb:rb/non-constant-kernel-open
+ -spec/ruby/core/io/foreach_spec.rb:rb/non-constant-kernel-open
+ -spec/ruby/core/io/write_spec.rb:rb/non-constant-kernel-open
+ -spec/ruby/core/io/read_spec.rb:rb/non-constant-kernel-open
+ -spec/ruby/core/kernel/open_spec.rb:rb/non-constant-kernel-open
+ input: sarif-results/${{ matrix.language }}.sarif
+ output: sarif-results/${{ matrix.language }}.sarif
+ if: ${{ matrix.language == 'ruby' }}
+ continue-on-error: true
+
+ - name: Upload SARIF
+ uses: github/codeql-action/upload-sarif@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
+ with:
+ sarif_file: sarif-results/${{ matrix.language }}.sarif
+ continue-on-error: true
diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml
new file mode 100644
index 0000000000..8c0ca54e0b
--- /dev/null
+++ b/.github/workflows/compilers.yml
@@ -0,0 +1,335 @@
+# Some tests depending on this name 'Compilations' via $GITHUB_WORKFLOW. Make sure to update such tests when renaming this workflow.
+name: Compilations
+
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+# Each job is split so that they roughly take 30min to run through.
+jobs:
+ compile-if:
+ name: 'omnibus compilations, trigger'
+ runs-on: ubuntu-latest
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+ steps:
+ - run: true
+ working-directory:
+
+ compile1:
+ name: 'omnibus compilations, #1'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - name: 'clang 18 LTO'
+ uses: './.github/actions/compilers'
+ with:
+ tag: clang-18
+ with_gcc: 'clang-18 -flto=auto'
+ optflags: '-O2'
+ enable_shared: false
+ timeout-minutes: 30
+ - { uses: './.github/actions/compilers', name: '-O0', with: { optflags: '-O0 -march=x86-64 -mtune=generic' }, timeout-minutes: 5 }
+ # - { uses: './.github/actions/compilers', name: '-O3', with: { optflags: '-O3 -march=x86-64 -mtune=generic', check: true } }
+
+ compile2:
+ name: 'omnibus compilations, #2'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - name: 'GCC 15 LTO'
+ uses: './.github/actions/compilers'
+ with:
+ tag: gcc-15
+ with_gcc: 'gcc-15 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch'
+ optflags: '-O2'
+ enable_shared: false
+ timeout-minutes: 10
+ - { uses: './.github/actions/compilers', name: 'ext/Setup', with: { static_exts: 'etc json/* */escape' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 15', with: { tag: 'gcc-15' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 14', with: { tag: 'gcc-14' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 13', with: { tag: 'gcc-13' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 12', with: { tag: 'gcc-12' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 11', with: { tag: 'gcc-11' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 10', with: { tag: 'gcc-10' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 9', with: { tag: 'gcc-9' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 8', with: { tag: 'gcc-8' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 7', with: { tag: 'gcc-7' }, timeout-minutes: 5 }
+
+ compile3:
+ name: 'omnibus compilations, #3'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'clang 22', with: { tag: 'clang-22' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 21', with: { tag: 'clang-21' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 20', with: { tag: 'clang-20' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 19', with: { tag: 'clang-19' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 18', with: { tag: 'clang-18' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 17', with: { tag: 'clang-17' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 16', with: { tag: 'clang-16' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 15', with: { tag: 'clang-15' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 14', with: { tag: 'clang-14' }, timeout-minutes: 5 }
+
+ compile4:
+ name: 'omnibus compilations, #4'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'clang 13', with: { tag: 'clang-13' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 12', with: { tag: 'clang-12' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 11', with: { tag: 'clang-11' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 10', with: { tag: 'clang-10' }, timeout-minutes: 5 }
+ # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o and fail `make test-leaked-globals`.
+ - { uses: './.github/actions/compilers', name: 'clang 9', with: { tag: 'clang-9', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 8', with: { tag: 'clang-8', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 7', with: { tag: 'clang-7', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 6', with: { tag: 'clang-6.0', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+
+ compile5:
+ name: 'omnibus compilations, #5'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ # -Wno-strict-prototypes is necessary with current clang-15 since
+ # older autoconf generate functions without prototype and -pedantic
+ # now implies strict-prototypes. Disabling the error but leaving the
+ # warning generates a lot of noise from use of ANYARGS in
+ # rb_define_method() and friends.
+ # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94
+ - { uses: './.github/actions/compilers', name: 'C99', with: { CFLAGS: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C11', with: { CFLAGS: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C17', with: { CFLAGS: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C23', with: { CFLAGS: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++98', with: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++11', with: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++14', with: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++17', with: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+
+ compile6:
+ name: 'omnibus compilations, #6'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'C++20', with: { CXXFLAGS: '-std=c++20 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++23', with: { CXXFLAGS: '-std=c++23 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++26', with: { CXXFLAGS: '-std=c++26 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'gmp', with: { append_configure: '--with-gmp', test_all: 'ruby/test_bignum.rb', test_spec: "/github/workspace/src/spec/ruby/core/integer" }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'jemalloc', with: { append_configure: '--with-jemalloc' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'valgrind', with: { append_configure: '--with-valgrind' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'coroutine=ucontext', with: { append_configure: '--with-coroutine=ucontext' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'coroutine=pthread', with: { append_configure: '--with-coroutine=pthread' }, timeout-minutes: 5 }
+
+ compile7:
+ name: 'omnibus compilations, #7'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'disable-jit', with: { append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'disable-yjit', with: { append_configure: '--disable-yjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'disable-zjit', with: { append_configure: '--disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'disable-dln', with: { append_configure: '--disable-dln' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'enable-mkmf-verbose', with: { append_configure: '--enable-mkmf-verbose' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'disable-rubygems', with: { append_configure: '--disable-rubygems' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RUBY_DEVEL', with: { append_configure: '--enable-devel' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=0', with: { cppflags: '-DOPT_THREADED_CODE=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=1', with: { cppflags: '-DOPT_THREADED_CODE=1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=2', with: { cppflags: '-DOPT_THREADED_CODE=2' }, timeout-minutes: 5 }
+
+ compile8:
+ name: 'omnibus compilations, #8'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'NDEBUG', with: { cppflags: '-DNDEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RUBY_DEBUG', with: { cppflags: '-DRUBY_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'ARRAY_DEBUG', with: { cppflags: '-DARRAY_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'BIGNUM_DEBUG', with: { cppflags: '-DBIGNUM_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'CCAN_LIST_DEBUG', with: { cppflags: '-DCCAN_LIST_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'CPDEBUG=-1', with: { cppflags: '-DCPDEBUG=-1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'ENC_DEBUG', with: { cppflags: '-DENC_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GC_DEBUG', with: { cppflags: '-DGC_DEBUG' }, timeout-minutes: 5 }
+
+ compile9:
+ name: 'omnibus compilations, #9'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'HASH_DEBUG', with: { cppflags: '-DHASH_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'ID_TABLE_DEBUG', with: { cppflags: '-DID_TABLE_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RGENGC_DEBUG=-1', with: { cppflags: '-DRGENGC_DEBUG=-1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'SYMBOL_DEBUG', with: { cppflags: '-DSYMBOL_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RGENGC_CHECK_MODE', with: { cppflags: '-DRGENGC_CHECK_MODE' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'VM_CHECK_MODE', with: { cppflags: '-DVM_CHECK_MODE' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_EMBED_CI=0', with: { cppflags: '-DUSE_EMBED_CI=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_FLONUM=0', with: { cppflags: '-DUSE_FLONUM=0', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+
+ compileX:
+ name: 'omnibus compilations, #10'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'USE_LAZY_LOAD', with: { cppflags: '-DUSE_LAZY_LOAD' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_SYMBOL_GC=0', with: { cppflags: '-DUSE_SYMBOL_GC=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_THREAD_CACHE=0', with: { cppflags: '-DUSE_THREAD_CACHE=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_RUBY_DEBUG_LOG=1', with: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_DEBUG_COUNTER', with: { cppflags: '-DUSE_DEBUG_COUNTER=1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'SHARABLE_MIDDLE_SUBSTRING', with: { cppflags: '-DSHARABLE_MIDDLE_SUBSTRING=1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'DEBUG_FIND_TIME_NUMGUESS', with: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'DEBUG_INTEGER_PACK', with: { cppflags: '-DDEBUG_INTEGER_PACK' }, timeout-minutes: 5 }
+
+ compileB:
+ name: 'omnibus compilations, #11'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'GC_DEBUG_STRESS_TO_CLASS', with: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GC_ENABLE_LAZY_SWEEP=0', with: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GC_PROFILE_DETAIL_MEMORY', with: { cppflags: '-DGC_PROFILE_DETAIL_MEMORY' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GC_PROFILE_MORE_DETAIL', with: { cppflags: '-DGC_PROFILE_MORE_DETAIL' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'MALLOC_ALLOCATED_SIZE_CHECK', with: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RGENGC_ESTIMATE_OLDMALLOC', with: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RGENGC_PROFILE', with: { cppflags: '-DRGENGC_PROFILE' }, timeout-minutes: 5 }
+
+ compileC:
+ name: 'omnibus compilations, #12'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'VM_DEBUG_BP_CHECK', with: { cppflags: '-DVM_DEBUG_BP_CHECK' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'VM_DEBUG_VERIFY_METHOD_CACHE', with: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'YJIT_FORCE_ENABLE', with: { cppflags: '-DYJIT_FORCE_ENABLE' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'UNIVERSAL_PARSER', with: { cppflags: '-DUNIVERSAL_PARSER' }, timeout-minutes: 5 }
+
+ compilemax:
+ name: 'omnibus compilations, result'
+ runs-on: ubuntu-latest
+ if: ${{ always() }}
+ needs:
+ - 'compile1'
+ - 'compile2'
+ - 'compile3'
+ - 'compile4'
+ - 'compile5'
+ - 'compile6'
+ - 'compile7'
+ - 'compile8'
+ - 'compile9'
+ - 'compileX'
+ - 'compileB'
+ - 'compileC'
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - uses: ./.github/actions/slack
+ with:
+ label: 'omnibus'
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+ - run: false
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml
new file mode 100644
index 0000000000..ac73991fe8
--- /dev/null
+++ b/.github/workflows/cygwin.yml
@@ -0,0 +1,71 @@
+name: Cygwin
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ runs-on: windows-2022
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - run: git config --global core.autocrlf input
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - name: Setup Cygwin
+ uses: cygwin/cygwin-install-action@master
+ with:
+ packages: ruby gcc-core make autoconf libtool libssl-devel libyaml-devel libffi-devel zlib-devel rubygems
+
+ - name: configure
+ run: |
+ ./autogen.sh
+ ./configure --disable-install-doc
+ shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}
+
+ - name: Extract bundled gems
+ run: |
+ make ruby -j5
+ make extract-gems
+ shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}
+
+ - name: make all
+ timeout-minutes: 30
+ run: make -j4 V=1
+ shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}
+
+ - uses: ./.github/actions/slack
+ with:
+ label: Cygwin
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/default_gems_list.yml b/.github/workflows/default_gems_list.yml
new file mode 100644
index 0000000000..1c7e2195c8
--- /dev/null
+++ b/.github/workflows/default_gems_list.yml
@@ -0,0 +1,99 @@
+name: Update default gems list
+on: [push, pull_request, merge_group]
+
+env:
+ UPDATE_NEWS_ENABLED: true
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ update_default_gems_list:
+ name: Update default gems list
+
+ permissions:
+ contents: write # for Git to git push
+
+ runs-on: ubuntu-latest
+
+ if: ${{ github.repository == 'ruby/ruby' }}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
+
+ - id: gems
+ run: true
+ if: ${{ github.ref == 'refs/heads/master' }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ makeup: true
+ # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN
+ checkout: '' # false (ref: https://github.com/actions/runner/issues/2238)
+ if: ${{ steps.gems.outcome == 'success' }}
+
+ - name: Download previous gems list
+ run: |
+ data=default_gems.json
+ mkdir -p .downloaded-cache
+ ln -s .downloaded-cache/$data .
+ curl -O -R -z ./$data https://stdgems.org/$data
+ if: ${{ steps.gems.outcome == 'success' }}
+
+ - name: Make default gems list
+ run: |
+ #!ruby
+ require 'rubygems'
+ $:.unshift "lib"
+ rgver = File.foreach("lib/rubygems.rb") do |line|
+ break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line
+ end
+ gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f|
+ spec = Gem::Specification.load(f)
+ "#{spec.name} #{spec.version}"
+ end.sort
+ File.open("gems/default_gems", "w") do |f|
+ f.puts "RubyGems #{rgver}"
+ f.puts gems
+ end
+ shell: ruby --disable=gems {0}
+ if: ${{ steps.gems.outcome == 'success' }}
+
+ - name: Maintain updated gems list in NEWS
+ run: |
+ ruby tool/update-NEWS-gemlist.rb default
+ if: ${{ steps.gems.outcome == 'success' && env.UPDATE_NEWS_ENABLED == 'true' }}
+
+ - name: Check diffs
+ id: diff
+ run: |
+ git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md ||
+ echo update=true >> $GITHUB_OUTPUT
+ if: ${{ steps.gems.outcome == 'success' }}
+
+ - name: Commit
+ run: |
+ git pull --ff-only origin ${GITHUB_REF#refs/heads/}
+ git commit --message="Update default gems list at ${GITHUB_SHA:0:30} [ci skip]" NEWS.md
+ git push origin ${GITHUB_REF#refs/heads/}
+ env:
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ if: >-
+ ${{
+ github.repository == 'ruby/ruby' &&
+ !startsWith(github.event_name, 'pull') &&
+ steps.diff.outputs.update
+ }}
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/dependabot_automerge.yml b/.github/workflows/dependabot_automerge.yml
new file mode 100644
index 0000000000..a95c7005c4
--- /dev/null
+++ b/.github/workflows/dependabot_automerge.yml
@@ -0,0 +1,32 @@
+# from https://github.com/gofiber/swagger/blob/main/.github/workflows/dependabot_automerge.yml
+name: Dependabot auto-merge
+on:
+ pull_request:
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ automerge:
+ runs-on: ubuntu-latest
+ if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'ruby/ruby'
+ steps:
+ - name: Dependabot metadata
+ uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
+ id: metadata
+
+ - name: Wait for status checks
+ uses: lewagon/wait-on-check-action@3603e826ee561ea102b58accb5ea55a1a7482343 # v1.4.1
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ ref: ${{ github.event.pull_request.head.sha || github.sha }}
+ check-regexp: 'make \(check, .*\)'
+ wait-interval: 30
+
+ - name: Auto-merge for Dependabot PRs
+ if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.update-type == 'version-update:semver-patch' }}
+ run: gh pr merge --auto --rebase "$PR_URL"
+ env:
+ PR_URL: ${{ github.event.pull_request.html_url }}
+ GITHUB_TOKEN: ${{ secrets.MATZBOT_DEPENDABOT_MERGE_TOKEN }}
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
new file mode 100644
index 0000000000..16dbac1afa
--- /dev/null
+++ b/.github/workflows/labeler.yml
@@ -0,0 +1,12 @@
+name: "Pull Request Labeler"
+on:
+- pull_request_target
+
+jobs:
+ labeler:
+ permissions:
+ contents: read
+ pull-requests: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/labeler@v6
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
new file mode 100644
index 0000000000..29adcab39a
--- /dev/null
+++ b/.github/workflows/macos.yml
@@ -0,0 +1,202 @@
+name: macOS
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ include:
+ - test_task: check
+ os: macos-14
+ - test_task: check
+ os: macos-14
+ configure_args: '--with-gcc=gcc-14'
+ - test_task: check
+ os: macos-14
+ configure_args: '--with-jemalloc --with-opt-dir=$(brew --prefix jemalloc)'
+ - test_task: check
+ os: macos-14
+ configure_args: '--with-gmp'
+ - test_task: test-all
+ test_opts: --repeat-count=2
+ os: macos-14
+ - test_task: test-bundler-parallel
+ os: macos-14
+ - test_task: test-bundled-gems
+ os: macos-14
+ - test_task: check
+ os: macos-15
+ fail-fast: false
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+
+ runs-on: ${{ matrix.os }}
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - name: Install libraries
+ uses: ./.github/actions/setup/macos
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ clean: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 0 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: make sure that kern.coredump=1
+ run: |
+ sysctl -n kern.coredump
+ sudo sysctl -w kern.coredump=1
+ sudo chmod -R +rwx /cores/
+
+ - name: Delete unused SDKs
+ # To free up disk space to not run out during the run
+ run: |
+ sudo rm -rf ~/.dotnet
+ sudo rm -rf /Library/Android
+ sudo rm -rf /Library/Developer/CoreSimulator
+ continue-on-error: true
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc ${ruby_configure_args} ${{ matrix.configure_args }}
+
+ - run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+
+ - run: make
+
+ - run: make hello
+
+ - name: runirb
+ run: |
+ echo IRB::VERSION | make runirb RUNOPT="-- -f"
+
+ - name: Set test options for skipped tests
+ run: |
+ set -x
+ TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')"
+ echo "TESTS=${TESTS}" >> $GITHUB_ENV
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+
+ - name: Set up Launchable
+ id: launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ${{ matrix.os }}
+ test-opts: ${{ matrix.test_opts }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ continue-on-error: true
+ timeout-minutes: 3
+
+ - name: Set extra test options
+ run: |
+ echo "TESTS=$TESTS ${{ matrix.test_opts }}" >> $GITHUB_ENV
+ echo "RUBY_TEST_TIMEOUT_SCALE=10" >> $GITHUB_ENV # With --repeat-count=2, flaky test by timeout occurs frequently for some reason
+ if: matrix.test_opts
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ ulimit -c unlimited
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
+ timeout-minutes: 90
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ PRECHECK_BUNDLED_GEMS: 'no'
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
+
+ - name: make skipped tests
+ run: |
+ make -s test-all TESTS="${TESTS//-n!\//-n/}"
+ env:
+ GNUMAKEFLAGS: ''
+ RUBY_TESTOPTS: '-v --tty=no'
+ PRECHECK_BUNDLED_GEMS: 'no'
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+
+ - name: CAPI extensions
+ uses: ./.github/actions/capiext
+ with:
+ builddir: build
+ env:
+ RUBY_TESTOPTS: '-v --tty=no'
+ if: ${{ contains(matrix.extra_checks, 'capi') }}
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.os }} / ${{ matrix.test_task }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ - name: Resolve job ID
+ id: job_id
+ uses: actions/github-script@main
+ env:
+ matrix: ${{ toJson(matrix) }}
+ with:
+ script: |
+ const { data: workflow_run } = await github.rest.actions.listJobsForWorkflowRun({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: context.runId
+ });
+ const matrix = JSON.parse(process.env.matrix);
+ const job_name = `${context.job}${matrix ? ` (${Object.values(matrix).join(", ")})` : ""}`;
+ return workflow_run.jobs.find((job) => job.name === job_name).id;
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: macos-latest
+ needs: [make]
+ steps:
+ - run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml
new file mode 100644
index 0000000000..5c639ad48b
--- /dev/null
+++ b/.github/workflows/mingw.yml
@@ -0,0 +1,243 @@
+name: MinGW
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+# Notes:
+# Actions console encoding causes issues, see test-all & test-spec steps
+#
+jobs:
+ make:
+ runs-on: windows-${{ matrix.os }}
+
+ name: ${{ github.workflow }} (${{ matrix.msystem }})
+
+ env:
+ MSYSTEM: ${{ matrix.msystem }}
+ MSYS2_ARCH: >-
+ ${{
+ contains(matrix.msystem, 'arm64') && 'aarch64' ||
+ contains(matrix.msystem, '64') && 'x86_64' || 'i686'
+ }}
+ MINGW_PACKAGE_PREFIX: >-
+ mingw-w${{
+ endsWith(matrix.msystem, '64') && '64' || '32'
+ }}-${{
+ startsWith(matrix.msystem, 'clang') && 'clang' ||
+ startsWith(matrix.msystem, 'ucrt') && 'ucrt' ||
+ 'mingw'
+ }}-${{
+ contains(matrix.msystem, 'arm64') && 'aarch64' ||
+ endsWith(matrix.msystem, '64') && 'x86_64' || 'i686'
+ }}
+ CFLAGS: '-mtune=generic -O3 -pipe'
+ CXXFLAGS: '-mtune=generic -O3 -pipe'
+ CPPFLAGS: '-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048'
+ LDFLAGS: '-pipe'
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+
+ strategy:
+ matrix:
+ include:
+ # To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses.
+ # Ruby 3.2 is the first Windows Ruby to use OpenSSL 3.x
+ - msystem: 'UCRT64'
+ os: 2022
+ test_task: 'check'
+ test-all-opts: '--name=!/TestObjSpace#test_reachable_objects_during_iteration/'
+ - msystem: 'CLANGARM64'
+ os: 11-arm
+ test_task: 'check'
+ fail-fast: false
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0
+ id: msys2
+ with:
+ msystem: ${{ matrix.msystem }}
+ update: true
+ install: >-
+ git
+ make
+ ruby
+ autoconf
+ ${{ env.MINGW_PACKAGE_PREFIX }}-gcc
+ ${{ env.MINGW_PACKAGE_PREFIX }}-ragel
+ ${{ env.MINGW_PACKAGE_PREFIX }}-openssl
+ ${{ env.MINGW_PACKAGE_PREFIX }}-libyaml
+ ${{ env.MINGW_PACKAGE_PREFIX }}-libffi
+
+ - name: Set up env
+ id: setup-env
+ working-directory:
+ run: |
+ $msys2 = ${env:MSYS2_LOCATION}
+ $msystem = ${env:MSYSTEM}.ToLower()
+ echo $msys2\usr\bin $msys2\$msystem\bin |
+ Tee-Object ${env:GITHUB_PATH} -Append -Encoding utf-8
+
+ # Use the fast device for the temporary directory.
+ # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
+ # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
+ $tmp = ${env:RUNNER_TEMP}
+ echo HOME=$home TMP=$tmp TEMP=$tmp TMPDIR=$tmp |
+ Tee-Object ${env:GITHUB_ENV} -Append -Encoding utf-8
+ shell: pwsh # cmd.exe does not strip spaces before `|`.
+ env:
+ MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
+ MSYSTEM: ${{ matrix.msystem }}
+
+ - name: Remove Strawberry Perl pkg-config
+ working-directory:
+ # `pkg-config.bat` included in Strawberry Perl is written in
+ # Perl and doesn't work when another msys2 `perl` precede its
+ # own `perl`.
+ #
+ # ```
+ # Can't find C:\Strawberry\perl\bin\pkg-config.bat on PATH, '.' not in PATH.
+ # ```
+ run: |
+ Get-Command pkg-config.bat | % { ren $_.path ($_.path + "~") }
+ shell: pwsh
+
+ - name: Misc system & package info
+ working-directory:
+ run: |
+ group() { echo ::group::$'\e[94;1m'"$*"$'\e[m'; }
+ endgroup() { echo ::endgroup::; }
+
+ group Path
+ cygpath -wa / . $(type -p cygpath bash sh)
+ endgroup
+
+ I() {
+ group $1
+ run Where type -pa $1 && { [ $# -eq 1 ] || run Version "$@"; } ||
+ failed+=($1)
+ endgroup
+ }
+ run() { local w m=$1; shift; w="$("$@")" && show "$m" && indent "$w"; }
+ indent() { [ -z "$1" ] || echo "$1" | /bin/sed '/^$/!s/^/ /'; }
+ show() { echo $'\e[96m'"$*"$'\e[m'; }
+
+ failed=()
+
+ I gcc.exe --version
+ I ragel.exe --version
+ I make.exe --version
+ I openssl.exe version
+ I libcrypto-3-x64.dll
+ I libssl-3-x64.dll
+
+ group Packages
+ pacman -Qs $MINGW_PACKAGE_PREFIX-* | /bin/sed -n "s,local/$MINGW_PACKAGE_PREFIX-,,p"
+ endgroup
+
+ [ ${#failed[@]} -eq 0 ]
+ shell: sh
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: configure
+ run: >
+ ../src/configure --disable-install-doc --prefix=/.
+ --build=$CHOST --host=$CHOST --target=$CHOST
+ shell: sh
+ env:
+ CHOST: ${{ env.MSYS2_ARCH }}-w64-mingw32
+
+ - name: make all
+ timeout-minutes: 30
+ run: make -j4
+
+ - name: make install
+ run: make DESTDIR=../install install-nodoc
+
+ - name: Set up Launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: windows-2022
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ test-tasks: '["test", "test-all", "test-spec"]'
+ continue-on-error: true
+ timeout-minutes: 3
+
+ - name: test
+ timeout-minutes: 30
+ run: make test test-tool
+ env:
+ GNUMAKEFLAGS: ''
+ RUBY_TESTOPTS: '-v --tty=no'
+ if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test' }}
+
+ - name: test-all
+ timeout-minutes: 45
+ run: |
+ make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }}
+ env:
+ RUBY_TESTOPTS: >-
+ --retry --job-status=normal --show-skip --timeout-scale=1.5 -j4
+ ${{ matrix.test-all-opts }}
+ ${{ env.TESTS }}
+ BUNDLER_VERSION:
+ if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-all' || StartsWith(matrix.test_task, 'test/') }}
+
+ - name: test-spec
+ timeout-minutes: 10
+ run: |
+ make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }}
+ if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/') }}
+
+ - uses: ./src/.github/actions/slack
+ with:
+ label: ${{ matrix.msystem }} / ${{ matrix.test_task }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
+ shell: cmd
diff --git a/.github/workflows/modgc.yml b/.github/workflows/modgc.yml
new file mode 100644
index 0000000000..1d14934df8
--- /dev/null
+++ b/.github/workflows/modgc.yml
@@ -0,0 +1,176 @@
+name: ModGC
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ check:
+ strategy:
+ matrix:
+ gc:
+ - name: default
+ - name: mmtk
+ mmtk_build: release
+ os: [macos-latest, ubuntu-latest]
+ include:
+ - test_task: check
+ fail-fast: false
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUBY_DEBUG: ci
+
+ runs-on: ${{ matrix.os }}
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - name: Install libraries (macOS)
+ uses: ./.github/actions/setup/macos
+ if: ${{ contains(matrix.os, 'macos') }}
+
+ - name: Install libraries (Ubuntu)
+ uses: ./.github/actions/setup/ubuntu
+ if: ${{ contains(matrix.os, 'ubuntu') }}
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+ if: ${{ contains(matrix.os, 'ubuntu') }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ clean: true
+ dummy-files: false
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: make sure that kern.coredump=1
+ run: |
+ sysctl -n kern.coredump
+ sudo sysctl -w kern.coredump=1
+ sudo chmod -R +rwx /cores/
+ if: ${{ contains(matrix.os, 'macos') }}
+
+ - name: Delete unused SDKs
+ # To free up disk space to not run out during the run
+ run: |
+ sudo rm -rf ~/.dotnet
+ sudo rm -rf /Library/Android
+ sudo rm -rf /Library/Developer/CoreSimulator
+ continue-on-error: true
+ if: ${{ contains(matrix.os, 'macos') }}
+
+ - name: Setup Ruby GC Directory
+ run: |
+ echo "MODULAR_GC_DIR=$HOME/ruby_gc" >> $GITHUB_ENV
+
+ - name: Run configure
+ env:
+ arch: ${{ matrix.arch }}
+ run: >-
+ $SETARCH ../src/configure -C --disable-install-doc --with-modular-gc=${{ env.MODULAR_GC_DIR }}
+ ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE}
+
+ - uses: actions-rust-lang/setup-rust-toolchain@v1
+ - name: Set MMTk environment variables
+ run: |
+ echo 'EXCLUDES=../src/test/.excludes-mmtk' >> $GITHUB_ENV
+ echo 'MSPECOPT=-B../src/spec/mmtk.mspec' >> $GITHUB_ENV
+ if: ${{ matrix.gc.name == 'mmtk' }}
+
+ - run: $SETARCH make
+
+ - name: Build Modular GC
+ run: |
+ echo "RUBY_GC_LIBRARY=${{ matrix.gc.name }}" >> $GITHUB_ENV
+ make install-modular-gc MODULAR_GC=${{ matrix.gc.name }} MMTK_BUILD=${{ matrix.gc.mmtk_build }}
+ make distclean-modular-gc MODULAR_GC=${{ matrix.gc.name }}
+
+ - run: $SETARCH make hello
+
+ - name: Set test options for skipped tests
+ run: |
+ set -x
+ TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')"
+ echo "TESTS=${TESTS}" >> $GITHUB_ENV
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+
+ - name: Set up Launchable
+ id: launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ${{ matrix.os || 'ubuntu-22.04' }}
+ test-opts: ${{ matrix.configure }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ continue-on-error: true
+ timeout-minutes: 3
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ $SETARCH make -s ${{ matrix.test_task }} \
+ ${TESTS:+TESTS="$TESTS"} \
+ ${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }}
+ timeout-minutes: ${{ matrix.gc.timeout || 40 }}
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ PRECHECK_BUNDLED_GEMS: 'no'
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
+
+ - name: make skipped tests
+ run: |
+ $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}"
+ env:
+ GNUMAKEFLAGS: ''
+ RUBY_TESTOPTS: '-v --tty=no'
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/parse_y.yml b/.github/workflows/parse_y.yml
new file mode 100644
index 0000000000..87facc8a55
--- /dev/null
+++ b/.github/workflows/parse_y.yml
@@ -0,0 +1,100 @@
+name: parse.y
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ include:
+ - test_task: check
+ - test_task: test-bundler-parallel
+ - test_task: test-bundled-gems
+ fail-fast: false
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUBY_DEBUG: ci
+ SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }}
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ clean: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG --with-parser=parse.y
+
+ - run: make
+
+ - run: make TESTRUN_SCRIPT='-renvutil -v -e "exit EnvUtil.current_parser == %[parse.y]"' run
+ env:
+ RUNOPT0: -I$(tooldir)/lib
+
+ - name: make ${{ matrix.test_task }}
+ run: make -s ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" SPECOPTS="$SPECOPTS"
+ env:
+ RUBY_TESTOPTS: ${{ matrix.testopts }}
+ EXCLUDES: '../src/test/.excludes-parsey'
+ RUN_OPTS: ${{ matrix.run_opts || '--parser=parse.y' }}
+ SPECOPTS: ${{ matrix.specopts || '-T --parser=parse.y' }}
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.run_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/post_push.yml b/.github/workflows/post_push.yml
new file mode 100644
index 0000000000..318444c0a2
--- /dev/null
+++ b/.github/workflows/post_push.yml
@@ -0,0 +1,85 @@
+name: Post-push
+on:
+ push:
+ branches:
+ - master
+ - 'ruby_*_*'
+jobs:
+ hooks:
+ name: Post-push hooks
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'ruby/ruby' }}
+ steps:
+ - name: Sync git.ruby-lang.org
+ run: |
+ mkdir -p ~/.ssh
+ (umask 066; printenv RUBY_GIT_SYNC_PRIVATE_KEY > ~/.ssh/id_ed25519)
+ ssh-keyscan -t ed25519 git.ruby-lang.org >> ~/.ssh/known_hosts
+ ssh -i ~/.ssh/id_ed25519 git-sync@git.ruby-lang.org "sudo -u git /home/git/git.ruby-lang.org/bin/update-ruby.sh $GITHUB_REF"
+ env:
+ GITHUB_REF: ${{ github.ref }}
+ RUBY_GIT_SYNC_PRIVATE_KEY: ${{ secrets.RUBY_GIT_SYNC_PRIVATE_KEY }}
+ if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }}
+
+ - name: Fetch changesets on bugs.ruby-lang.org
+ run: |
+ curl "https://bugs.ruby-lang.org/sys/fetch_changesets?key=${REDMINE_SYS_API_KEY}" -s --fail-with-body -w '* status: %{http_code}\n'
+ env:
+ REDMINE_SYS_API_KEY: ${{ secrets.REDMINE_SYS_API_KEY }}
+ if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }}
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ fetch-depth: 500 # for notify-slack-commits
+ token: ${{ secrets.MATZBOT_AUTO_UPDATE_TOKEN }}
+
+ - name: Notify commit to Slack
+ run: ruby tool/notify-slack-commits.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.before }}
+ GITHUB_NEW_SHA: ${{ github.event.after }}
+ SLACK_WEBHOOK_URL_ALERTS: ${{ secrets.SLACK_WEBHOOK_URL_ALERTS }}
+ SLACK_WEBHOOK_URL_COMMITS: ${{ secrets.SLACK_WEBHOOK_URL_COMMITS }}
+ SLACK_WEBHOOK_URL_RUBY_JP: ${{ secrets.SLACK_WEBHOOK_URL_RUBY_JP }}
+ if: ${{ github.ref == 'refs/heads/master' }}
+
+ - name: Notify commit to ruby-cvs
+ run: |
+ SENDMAIL="ssh -i ${HOME}/.ssh/id_ed25519 git-sync@git.ruby-lang.org /usr/sbin/sendmail" \
+ ruby tool/commit-email.rb . ruby-cvs@g.ruby-lang.org \
+ "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" "$GITHUB_REF" \
+ --viewer-uri "https://github.com/ruby/ruby/commit/" \
+ --error-to cvs-admin@ruby-lang.org
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.before }}
+ GITHUB_NEW_SHA: ${{ github.event.after }}
+ GITHUB_REF: ${{ github.ref }}
+ if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }}
+
+ - name: Auto-correct code styles
+ run: |
+ set -x
+ ruby tool/auto-style.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.before }}
+ GITHUB_NEW_SHA: ${{ github.event.after }}
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ EMAIL: svn-admin@ruby-lang.org
+ if: ${{ github.ref == 'refs/heads/master' }}
+
+ - name: Push PR notes to GitHub
+ run: ruby tool/notes-github-pr.rb "$(pwd)/.git" "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.before }}
+ GITHUB_NEW_SHA: ${{ github.event.after }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ EMAIL: svn-admin@ruby-lang.org
+ if: ${{ github.ref == 'refs/heads/master' }}
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/pr-playground.yml b/.github/workflows/pr-playground.yml
new file mode 100644
index 0000000000..f3c0556429
--- /dev/null
+++ b/.github/workflows/pr-playground.yml
@@ -0,0 +1,127 @@
+name: Post Playground link to PR
+on:
+ pull_request_target:
+ types: [labeled]
+ workflow_run:
+ workflows: ["WebAssembly"]
+ types: [completed]
+
+jobs:
+ post-summary:
+ name: Post Playground link
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ # Post a comment only if the PR status check is passed and the PR is labeled with `Playground`.
+ # Triggered twice: when the PR is labeled and when PR build is passed.
+ if: >-
+ ${{ false
+ || (true
+ && github.event_name == 'pull_request_target'
+ && contains(github.event.pull_request.labels.*.name, 'Playground'))
+ || (true
+ && github.event_name == 'workflow_run'
+ && github.event.workflow_run.conclusion == 'success'
+ && github.event.workflow_run.event == 'pull_request')
+ }}
+ steps:
+ - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const fs = require('fs/promises');
+
+ const buildWorkflowPath = '.github/workflows/wasm.yml';
+ const findSuccessfuBuildRun = async (pr) => {
+ const opts = github.rest.actions.listWorkflowRunsForRepo.endpoint.merge({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ status: 'success',
+ branch: pr.head.ref,
+ });
+ const runs = await github.paginate(opts);
+ const buildRun = runs.find(run => run.path == buildWorkflowPath);
+ return buildRun;
+ }
+
+ const postComment = async (body, pr) => {
+ const { data: comments } = await github.rest.issues.listComments({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: pr.number,
+ });
+
+ const commentOpts = { owner: context.repo.owner, repo: context.repo.repo, body: comment };
+
+ const existingComment = comments.find(comment => comment.body.startsWith(magicComment));
+ if (existingComment) {
+ core.info(`Updating existing comment: ${existingComment.html_url}`);
+ await github.rest.issues.updateComment({
+ ...commentOpts, comment_id: existingComment.id
+ });
+ } else {
+ await github.rest.issues.createComment({
+ ...commentOpts, issue_number: pr.number
+ });
+ }
+ }
+
+ const derivePRNumber = async () => {
+ if (context.payload.pull_request) {
+ return context.payload.pull_request.number;
+ }
+ // Workaround for https://github.com/orgs/community/discussions/25220
+
+ const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: context.payload.workflow_run.id,
+ });
+ const artifact = artifacts.find(artifact => artifact.name == 'github-pr-info');
+ if (!artifact) {
+ throw new Error('Cannot find github-pr-info.txt artifact');
+ }
+
+ const { data } = await github.rest.actions.downloadArtifact({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ artifact_id: artifact.id,
+ archive_format: 'zip',
+ });
+
+ await fs.writeFile('pr-info.zip', Buffer.from(data));
+ await exec.exec('unzip', ['pr-info.zip']);
+ return await fs.readFile('github-pr-info.txt', 'utf8');
+ }
+
+ const prNumber = await derivePRNumber();
+
+ const { data: pr } = await github.rest.pulls.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: prNumber,
+ });
+
+ core.info(`Checking if the PR ${prNumber} is labeled with Playground...`);
+ if (!pr.labels.some(label => label.name == 'Playground')) {
+ core.info(`The PR is not labeled with Playground.`);
+ return;
+ }
+
+ core.info(`Checking if the build is successful for ${pr.head.ref} in ${pr.head.repo.owner.login}/${pr.head.repo.name}...`);
+ const buildRun = await findSuccessfuBuildRun(pr);
+ if (!buildRun) {
+ core.info(`No successful build run found for ${buildWorkflowPath} on ${pr.head.ref} yet.`);
+ return;
+ }
+ core.info(`Found a successful build run: ${buildRun.html_url}`);
+
+ const runLink = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
+ const magicComment = `<!-- AUTO-GENERATED-COMMENT-PR-PLAYGROUND -->`;
+ const comment = `${magicComment}
+ **Try on Playground**: https://ruby.github.io/play-ruby?run=${buildRun.id}
+ This is an automated comment by [\`pr-playground.yml\`](${runLink}) workflow.
+ `;
+ core.info(`Comment: ${comment}`);
+ await postComment(comment, pr);
+
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000000..3caeee9a3b
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,107 @@
+name: Publish Ruby packages
+
+on:
+ repository_dispatch:
+ types:
+ - release
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Version of the Ruby package to release'
+ required: true
+ default: '3.3.4'
+
+jobs:
+ release:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6.0.1
+
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 3.3.4
+
+ - name: Store Ruby version
+ run: |
+ echo "RUBY_VERSION=${{ github.event.client_payload.version || github.event.inputs.version }}" >> $GITHUB_ENV
+
+ - name: Store ABI version
+ run: echo "ABI_VERSION=$(echo ${{ env.RUBY_VERSION }} | cut -d '.' -f 1-2)" >> $GITHUB_ENV
+
+ - name: Copy draft package `/tmp` to `/pub` directory
+ run: tool/release.sh ${{ env.RUBY_VERSION }}
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.FTP_R_L_O_AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.FTP_R_L_O_AWS_SECRET_ACCESS_KEY }}
+ AWS_DEFAULT_REGION: us-west-2
+
+ - name: Purge URLs of release package
+ run: |
+ curl -X POST \
+ -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \
+ https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.tar.gz
+ curl -X POST \
+ -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \
+ https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.tar.xz
+ curl -X POST \
+ -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \
+ https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.zip
+
+ - name: Create a release on GitHub
+ run: |
+ RELEASE_TAG=$(ruby tool/ruby-version.rb tag "${{ env.RUBY_VERSION }}")
+ echo $RELEASE_TAG
+ PREVIOUS_RELEASE_TAG=$(ruby tool/ruby-version.rb previous-tag "${{ env.RUBY_VERSION }}")
+ echo $PREVIOUS_RELEASE_TAG
+ tool/gen-github-release.rb $PREVIOUS_RELEASE_TAG $RELEASE_TAG --no-dry-run
+ env:
+ GITHUB_TOKEN: ${{ secrets.MATZBOT_AUTO_UPDATE_TOKEN }}
+
+ - name: Update versions index
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/actions/dispatches \
+ -d '{"event_type": "update_index"}'
+
+ - name: Build and push Docker images
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/docker-images/actions/workflows/build.yml/dispatches \
+ -d '{"ref": "master", "inputs": {"ruby_version": "${{ env.RUBY_VERSION }}"}}'
+
+ - name: Build snapcraft packages
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/snap.ruby/dispatches \
+ -d '{"event_type": "build", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}"}}'
+
+ - name: Store the latest LTS version of OpenSSL
+ run: |
+ echo "OPENSSL_VERSION=`curl -s https://api.github.com/repos/openssl/openssl/releases | jq -r '.[].tag_name | select(startswith("openssl-3.0"))' | sort -Vr | head -n1 | cut -d'-' -f2`" >> $GITHUB_ENV
+
+ - name: Update ruby-build definition
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.RUBY_BUILD_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/rbenv/ruby-build/dispatches \
+ -d '{"event_type": "update-ruby", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}", "openssl_version": "${{ env.OPENSSL_VERSION }}"}}'
+
+ - name: Update all-ruby definition
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/all-ruby/dispatches \
+ -d '{"event_type": "update"}'
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000000..5d4474d978
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,18 @@
+name: Start release workflow
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ notify:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Build release package
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/actions/dispatches \
+ -d '{"event_type": "${{ github.ref }}"}'
diff --git a/.github/workflows/rust-warnings.yml b/.github/workflows/rust-warnings.yml
new file mode 100644
index 0000000000..a2e3208e52
--- /dev/null
+++ b/.github/workflows/rust-warnings.yml
@@ -0,0 +1,60 @@
+# Surface Rust warnings on PRs that touch any Rust code.
+# Not a required check so we never block people over new warnings
+# that might come from a new Rust version being released.
+name: Rust warnings
+on:
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ paths:
+ - '**.rs'
+ - '!**.inc.rs'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ rust-warnings:
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+
+ runs-on: ubuntu-24.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - name: Install Rust
+ run: rustup default beta
+
+ - name: Rust warnings
+ shell: bash
+ run: |
+ set -eu
+ cargo check --quiet --all-features --message-format=json \
+ | jq -r 'select(.message.level | IN("warning", "error")) | .message.rendered' \
+ | tee messages.txt
+ (exit "${PIPESTATUS[0]}") && ! grep --quiet '[^[:space:]]' messages.txt
+
+ - name: "📜 `rustdoc` warnings"
+ shell: bash
+ run: |
+ set -eu
+ cargo doc --document-private-items --all --no-deps --message-format=json \
+ | jq -r 'select(.message.level | IN("warning", "error")) | .message.rendered' \
+ | tee messages.txt
+ (exit "${PIPESTATUS[0]}") && ! grep --quiet '[^[:space:]]' messages.txt
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
new file mode 100644
index 0000000000..c607098997
--- /dev/null
+++ b/.github/workflows/scorecards.yml
@@ -0,0 +1,78 @@
+# This workflow uses actions that are not certified by GitHub. They are provided
+# by a third-party and are governed by separate terms of service, privacy
+# policy, and support documentation.
+
+name: Scorecard supply-chain security
+on:
+ # For Branch-Protection check. Only the default branch is supported. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
+ branch_protection_rule:
+ # To guarantee Maintained check is occasionally updated. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
+ schedule:
+ - cron: '39 3 * * 5'
+ # push:
+ # branches: [ "master" ]
+
+# Declare default permissions as read only.
+permissions: read-all
+
+jobs:
+ analysis:
+ name: Scorecard analysis
+ runs-on: ubuntu-latest
+ # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
+ if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
+ permissions:
+ # Needed to upload the results to code-scanning dashboard.
+ security-events: write
+ # Needed to publish results and get a badge (see publish_results below).
+ id-token: write
+ # Uncomment the permissions below if installing in a private repository.
+ # contents: read
+ # actions: read
+
+ steps:
+ - name: "Checkout code"
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ persist-credentials: false
+
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ # (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
+ # - you want to enable the Branch-Protection check on a *public* repository, or
+ # - you are installing Scorecard on a *private* repository
+ # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
+ # repo_token: ${{ secrets.SCORECARD_TOKEN }}
+
+ # Public repositories:
+ # - Publish results to OpenSSF REST API for easy access by consumers
+ # - Allows the repository to include the Scorecard badge.
+ # - See https://github.com/ossf/scorecard-action#publishing-results.
+ # For private repositories:
+ # - `publish_results` will always be set to `false`, regardless
+ # of the value entered here.
+ publish_results: true
+
+ # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
+ # file_mode: git
+
+ # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
+ # format to the repository Actions tab.
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
+
+ # 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@v4
+ with:
+ sarif_file: results.sarif
diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml
new file mode 100644
index 0000000000..cf4661555c
--- /dev/null
+++ b/.github/workflows/spec_guards.yml
@@ -0,0 +1,67 @@
+name: Rubyspec Version Guards Check
+
+on:
+ push:
+ paths:
+ - '.github/workflows/spec_guards.yml'
+ - 'spec/**'
+ - '!spec/*.md'
+ pull_request:
+ paths:
+ - '.github/workflows/spec_guards.yml'
+ - 'spec/**'
+ - '!spec/*.md'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ rubyspec:
+ name: Rubyspec
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ strategy:
+ matrix:
+ # Specs from ruby/spec should still run on all supported Ruby versions.
+ # This also ensures the needed ruby_version_is guards are there, see spec/README.md.
+ ruby:
+ - ruby-3.2
+ - ruby-3.3
+ - ruby-3.4
+ - ruby-4.0
+ fail-fast: false
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler: none
+
+ - run: gem install webrick
+
+ - run: ruby ../mspec/bin/mspec
+ working-directory: spec/ruby
+ env:
+ CHECK_LEAKS: true
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.ruby }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/sync_default_gems.yml b/.github/workflows/sync_default_gems.yml
new file mode 100644
index 0000000000..9ff97d5a4e
--- /dev/null
+++ b/.github/workflows/sync_default_gems.yml
@@ -0,0 +1,77 @@
+name: Sync default gems
+
+env:
+ DEFAULT_GEM_SYNC_ENABLED: true
+
+on:
+ workflow_dispatch:
+ inputs:
+ gem:
+ required: true
+ description: 'Name of the gem to be synchronized'
+ type: string
+ before:
+ required: true
+ description: 'Gem commit SHA before sync'
+ type: string
+ after:
+ required: true
+ description: 'Gem commit SHA after sync'
+ type: string
+
+jobs:
+ sync_default_gems:
+ name: Sync default gem ${{ github.event.inputs.gem }}
+
+ permissions:
+ contents: write # for Git to git push
+
+ runs-on: ubuntu-latest
+
+ if: ${{ github.repository == 'ruby/ruby' }}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ name: Check out ruby/ruby
+ with:
+ token: ${{ github.repository == 'ruby/ruby' && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.4'
+ bundler: none
+
+ - name: Run tool/sync_default_gems.rb
+ id: sync
+ run: |
+ ruby_before=$(git rev-parse HEAD)
+ set -x
+ ruby tool/sync_default_gems.rb "${gem_name}" "${gem_before}..${gem_after}"
+ if [[ "$(git rev-parse HEAD)" != "$ruby_before" ]]; then
+ echo update=true >> $GITHUB_OUTPUT
+ fi
+ env:
+ gem_name: ${{ github.event.inputs.gem }}
+ gem_before: ${{ github.event.inputs.before }}
+ gem_after: ${{ github.event.inputs.after }}
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+
+ - name: Push
+ run: |
+ git pull --rebase origin ${GITHUB_REF#refs/heads/}
+ git push origin ${GITHUB_REF#refs/heads/}
+ if: ${{ steps.sync.outputs.update && env.DEFAULT_GEM_SYNC_ENABLED == 'true' }}
+ env:
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ label: "${{ github.event.inputs.gem }} (<https://github.com/${{ github.event.inputs.gem == 'rubygems' && 'rubygems' || 'ruby' }}/${{ github.event.inputs.gem }}/compare/${{ github.event.inputs.before }}...${{ github.event.inputs.after }}|diff>)"
+ event_name: workflow_dispatch
+ extra_channel_id: C05FPKAU743 # alerts-sync
+ if: ${{ failure() }}
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
new file mode 100644
index 0000000000..88c19b6fe6
--- /dev/null
+++ b/.github/workflows/ubuntu.yml
@@ -0,0 +1,269 @@
+name: Ubuntu
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ # We enumerate every job in matrix.include to save build time
+ include:
+ - test_task: check
+ configure: 'cppflags=-DVM_CHECK_MODE'
+ - test_task: check
+ arch: i686
+ - test_task: check
+ configure: '--disable-yjit'
+ - test_task: check
+ configure: '--enable-shared --enable-load-relative'
+ - test_task: test-bundler-parallel
+ timeout: 50
+ - test_task: test-bundled-gems
+ - test_task: check
+ os: ubuntu-24.04
+ extra_checks: [capi]
+ # ubuntu-24.04-arm jobs don't start on ruby/ruby as of 2025-10-29
+ #- test_task: check
+ # os: ubuntu-24.04-arm
+ fail-fast: false
+
+ env: &make-env
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUBY_DEBUG: ci
+
+ runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps: &make-steps
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/ubuntu
+ with:
+ arch: ${{ matrix.arch }}
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+ if: >-
+ ${{ !endsWith(matrix.os, 'arm')
+ && !endsWith(matrix.os, 'ppc64le') && !endsWith(matrix.os, 's390x') }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ clean: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: Run configure
+ env:
+ arch: ${{ matrix.arch }}
+ configure: ${{ matrix.configure }}
+ run: >-
+ $SETARCH ../src/configure -C --disable-install-doc ${configure:-cppflags=-DRUBY_DEBUG}
+ ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE}
+
+ - run: $SETARCH make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+
+ - run: $SETARCH make
+
+ - run: $SETARCH make hello
+
+ - name: runirb
+ run: |
+ echo IRB::VERSION | $SETARCH make runirb RUNOPT="-- -f"
+
+ - name: Set test options for skipped tests
+ run: |
+ set -x
+ TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')"
+ echo "TESTS=${TESTS}" >> $GITHUB_ENV
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+
+ - name: Set up Launchable
+ id: launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ${{ matrix.os || 'ubuntu-22.04' }}
+ test-opts: ${{ matrix.configure }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ continue-on-error: true
+ timeout-minutes: 3
+
+ # Avoid possible test failures with the zlib applying the following patch
+ # on s390x CPU architecture.
+ # https://github.com/madler/zlib/pull/410
+ - name: Disable DFLTCC
+ run: echo "DFLTCC=0" >> $GITHUB_ENV
+ if: ${{ endsWith(matrix.os, 's390x') }}
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ $SETARCH make -s ${{ matrix.test_task }} \
+ ${TESTS:+TESTS="$TESTS"} \
+ ${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }}
+ timeout-minutes: ${{ matrix.timeout || 40 }}
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ PRECHECK_BUNDLED_GEMS: 'no'
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
+
+ - name: make skipped tests
+ run: |
+ $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}"
+ env:
+ GNUMAKEFLAGS: ''
+ RUBY_TESTOPTS: '-v --tty=no'
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+
+ - name: test-pc
+ run: |
+ DESTDIR=${RUNNER_TEMP-${TMPDIR-/tmp}}/installed
+ $SETARCH make test-pc "DESTDIR=$DESTDIR"
+
+ - name: CAPI extensions
+ uses: ./.github/actions/capiext
+ with:
+ builddir: build
+ make: '$SETARCH make'
+ env:
+ RUBY_TESTOPTS: '-v --tty=no'
+ if: ${{ contains(matrix.extra_checks, 'capi') }}
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}${{ matrix.os }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ make-ibm:
+ strategy:
+ matrix:
+ include:
+ - test_task: check
+ os: ubuntu-24.04-ppc64le
+ - test_task: check
+ os: ubuntu-24.04-s390x
+ fail-fast: false
+
+ env: *make-env
+
+ runs-on: ${{ matrix.os }}
+
+ if: >-
+ ${{github.repository == 'ruby/ruby'
+ && !(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps: *make-steps
+
+ # Separated from `make` job to avoid making it a required status check
+ ruby-bench:
+ strategy:
+ matrix:
+ include:
+ # Using the same setup as ZJIT jobs
+ - bench_opts: '--warmup=1 --bench=1 --excludes=lobsters'
+
+ runs-on: ubuntu-24.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install"
+
+ - run: make install
+
+ - name: Checkout ruby-bench
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ repository: ruby/ruby-bench
+ path: ruby-bench
+
+ # If you want to skip failing benchmark, consider using `--excludes`.
+ # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'`
+ - name: Run ruby-bench
+ run: ruby run_benchmarks.rb -e "ruby::../build/install/bin/ruby" ${{ matrix.bench_opts }}
+ working-directory: ruby-bench
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: ubuntu-latest
+ needs: [make]
+ steps:
+ - run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml
new file mode 100644
index 0000000000..0d2a6f0545
--- /dev/null
+++ b/.github/workflows/wasm.yml
@@ -0,0 +1,179 @@
+name: WebAssembly
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ entry:
+# # wasmtime can't compile non-optimized Asyncified binary due to locals explosion
+# - { name: O0-debuginfo, optflags: '-O0', debugflags: '-g', wasmoptflags: '-O1' }
+# - { name: O1, optflags: '-O1', debugflags: '' , wasmoptflags: '-O1' }
+ - { name: O2, optflags: '-O2', debugflags: '', wasmoptflags: '-O2' }
+# - { name: O3, optflags: '-O3', debugflags: '' , wasmoptflags: '-O3' }
+# # -O4 is equivalent to -O3 in clang, but it's different in wasm-opt
+# - { name: O4, optflags: '-O3', debugflags: '' , wasmoptflags: '-O4' }
+# - { name: Oz, optflags: '-Oz', debugflags: '' , wasmoptflags: '-Oz' }
+ fail-fast: false
+
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ WASI_SDK_VERSION_MAJOR: 25
+ WASI_SDK_VERSION_MINOR: 0
+ BINARYEN_VERSION: 113
+ WASMTIME_VERSION: v15.0.0
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - name: Install libraries
+ run: |
+ set -ex
+ sudo apt-get update -q || :
+ sudo apt-get install --no-install-recommends -q -y ruby make autoconf git wget
+
+ wasi_sdk_deb="wasi-sdk-${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}-x86_64-linux.deb"
+ wget "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION_MAJOR}/${wasi_sdk_deb}"
+ sudo dpkg -i "$wasi_sdk_deb"
+ rm -f "$wasi_sdk_deb"
+
+ mkdir build-sdk
+ pushd build-sdk
+
+ wasmtime_url="https://github.com/bytecodealliance/wasmtime/releases/download/${WASMTIME_VERSION}/wasmtime-${WASMTIME_VERSION}-x86_64-linux.tar.xz"
+ wget -O - "$wasmtime_url" | tar xJf -
+ sudo ln -fs "$PWD/wasmtime-${WASMTIME_VERSION}-x86_64-linux/wasmtime" /usr/local/bin/wasmtime
+
+ binaryen_tarball="binaryen-version_${BINARYEN_VERSION}-x86_64-linux.tar.gz"
+ binaryen_url="https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VERSION}/${binaryen_tarball}"
+ wget -O - "$binaryen_url" | tar xfz -
+ sudo ln -fs "$PWD/binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt" /usr/local/bin/wasm-opt
+ working-directory: src
+
+ - name: Set ENV
+ run: |
+ echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+
+ - name: Build baseruby
+ run: |
+ set -ex
+ mkdir ../baseruby
+ pushd ../baseruby
+ ../src/configure --prefix=$PWD/install
+ make
+ make install
+
+ - name: Download config.guess with wasi version
+ run: |
+ rm tool/config.guess tool/config.sub
+ ruby tool/downloader.rb -d tool -e gnu config.guess config.sub
+ working-directory: src
+
+ - name: Run configure
+ run: |
+ ../src/configure \
+ --host wasm32-unknown-wasi \
+ --with-baseruby=$PWD/../baseruby/install/bin/ruby \
+ --with-static-linked-ext \
+ --with-ext=cgi/escape,continuation,coverage,date,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,json,json/generator,json/parser,objspace,pathname,rbconfig/sizeof,ripper,stringio,strscan,monitor \
+ LDFLAGS=" \
+ -Xlinker --stack-first \
+ -Xlinker -z -Xlinker stack-size=16777216 \
+ " \
+ optflags="${{ matrix.entry.optflags }}" \
+ debugflags="${{ matrix.entry.debugflags }}" \
+ wasmoptflags="${{ matrix.entry.wasmoptflags }} ${{ matrix.entry.debugflags }}"
+
+ # miniruby may not be built when cross-compling
+ - run: make mini ruby
+
+ - run: make install DESTDIR=$PWD/../install
+ - run: tar cfz ../install.tar.gz -C ../install .
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: ruby-wasm-install
+ path: ${{ github.workspace }}/install.tar.gz
+ - name: Show Playground URL to try the build
+ run: |
+ echo "Try on Playground: https://ruby.github.io/play-ruby?run=$GITHUB_RUN_ID" >> $GITHUB_STEP_SUMMARY
+
+ - name: Run basictest
+ run: wasmtime run ./../build/miniruby --mapdir /::./ -- basictest/test.rb
+ working-directory: src
+
+ - name: Run bootstraptest (no thread)
+ run: |
+ NO_THREAD_TESTS="$(grep -L Thread -R ./bootstraptest | awk -F/ '{ print $NF }' | uniq | sed -n 's/test_\(.*\).rb/\1/p' | paste -s -d, -)"
+ ruby ./bootstraptest/runner.rb --ruby="$(which wasmtime) run $PWD/../build/ruby --mapdir /::./ -- " --verbose "--sets=$NO_THREAD_TESTS"
+ working-directory: src
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.entry.name }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ # Workaround for https://github.com/orgs/community/discussions/25220
+ - name: Save Pull Request number
+ if: ${{ github.event_name == 'pull_request' }}
+ run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ if: ${{ github.event_name == 'pull_request' }}
+ with:
+ name: github-pr-info
+ path: ${{ github.workspace }}/github-pr-info.txt
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
new file mode 100644
index 0000000000..1d44a5482c
--- /dev/null
+++ b/.github/workflows/windows.yml
@@ -0,0 +1,201 @@
+name: Windows
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ include:
+ - os: 2022
+ vc: 2022
+ test_task: check
+ - os: 2025
+ vc: 2022
+ test_task: check
+ - os: 11-arm
+ test_task: 'btest test-basic test-tool' # check and test-spec are broken yet.
+ target: arm64
+ - os: 2025
+ vc: 2022
+ test_task: test-bundled-gems
+ fail-fast: false
+
+ runs-on: windows-${{ matrix.os }}
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ name: Windows ${{ matrix.os }}/Visual C++ ${{ matrix.vc }} (${{ matrix.test_task }})
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ VCPKG_DEFAULT_TRIPLET: ${{ matrix.target || 'x64' }}-windows
+
+ steps:
+ - run: md build
+ working-directory:
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.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' }}
+ bundler: none
+ windows-toolchain: none
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ make-command: nmake
+ clean: true
+
+ - name: Install tools with scoop
+ run: |
+ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
+ iwr -useb get.scoop.sh | iex
+ Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
+ scoop install vcpkg uutils-coreutils
+ shell: pwsh
+
+ - name: Restore vcpkg artifact
+ id: restore-vcpkg
+ uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
+ with:
+ path: src\vcpkg_installed
+ key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }}
+
+ - name: Install libraries with vcpkg
+ run: |
+ vcpkg install --vcpkg-root=%USERPROFILE%\scoop\apps\vcpkg\current
+ working-directory: src
+ if: ${{ ! steps.restore-vcpkg.outputs.cache-hit }}
+
+ - name: Save vcpkg artifact
+ uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
+ with:
+ path: src\vcpkg_installed
+ key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }}
+ if: ${{ ! steps.restore-vcpkg.outputs.cache-hit && (github.ref_name == 'master' || startsWith(github.ref_name, 'ruby_')) }}
+
+ - name: setup env
+ # Available Ruby versions: https://github.com/actions/runner-images/blob/main/images/windows/Windows2019-Readme.md#ruby
+ # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
+ # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
+ run: |
+ ::- Set up VC ${{ matrix.vc }}
+ set | sort > old.env
+ call ..\src\win32\vssetup.cmd ^
+ -arch=${{ matrix.target || 'amd64' }} ^
+ ${{ matrix.vcvars && '-vcvars_ver=' || '' }}${{ matrix.vcvars }}
+ nmake -f nul
+ set TMP=%RUNNER_TEMP%
+ set TEMP=%RUNNER_TEMP%
+ set MAKEFLAGS=l
+ set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul
+ set RUBY_OPT_DIR=%GITHUB_WORKSPACE:\=/%/src/vcpkg_installed/%VCPKG_DEFAULT_TRIPLET%
+ set | sort > new.env
+ comm -13 old.env new.env >> %GITHUB_ENV%
+ del *.env
+
+ - name: baseruby version
+ run: ruby -v
+
+ - name: compiler version
+ run: cl
+
+ - name: volume info
+ run: Get-Volume
+ shell: pwsh
+
+ # TODO: We should use `../src` instead of `D:/a/ruby/ruby/src`
+ - name: Configure
+ run: >-
+ ../src/win32/configure.bat --disable-install-doc
+ --with-opt-dir=%RUBY_OPT_DIR%
+ --with-gmp
+
+ - run: nmake prepare-vcpkg
+
+ - run: nmake incs
+
+ - run: nmake extract-extlibs
+
+ # On all other platforms, test-spec depending on extract-gems (in common.mk) is enough.
+ # But not for this Visual Studio workflow. So here we extract gems before building.
+ - run: nmake extract-gems
+
+ # windows-11-arm runner cannot run `ruby tool/file2lastrev.rb --revision.h --output=revision.h`
+ - name: make revision.h
+ run: |
+ win32\lastrev.bat | win32\ifchange.bat --timestamp=.revision.time revision.h -
+ type revision.h
+ working-directory: src
+
+ - run: nmake
+
+ - name: Set up Launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: windows-${{ matrix.os }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ test-task: ${{ matrix.test_task || 'check' }}
+ continue-on-error: true
+ if: ${{ matrix.test_task != 'test-bundled-gems' }}
+ timeout-minutes: 3
+
+ - run: nmake ${{ matrix.test_task || 'check' }}
+ env:
+ RUBY_TESTOPTS: -j${{ env.TEST_JOBS || 4 }}
+ timeout-minutes: 70
+
+ - uses: ./.github/actions/slack
+ with:
+ label: Windows ${{ matrix.os }} / VC ${{ matrix.vc }} / ${{ matrix.test_task || 'check' }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: windows-latest
+ needs: [make]
+ steps:
+ - run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+defaults:
+ run:
+ working-directory: build
+ shell: cmd
diff --git a/.github/workflows/wsl.yml b/.github/workflows/wsl.yml
new file mode 100644
index 0000000000..640f18ce42
--- /dev/null
+++ b/.github/workflows/wsl.yml
@@ -0,0 +1,70 @@
+name: Ubuntu on WSL
+
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+jobs:
+ wsl:
+ runs-on: windows-2025
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - name: Install or update WSL
+ uses: Ubuntu/WSL/.github/actions/wsl-install@main
+ with:
+ distro: Ubuntu-24.04
+
+ - name: Install dependencies
+ uses: Ubuntu/WSL/.github/actions/wsl-bash@main
+ with:
+ distro: Ubuntu-24.04
+ working-dir: /tmp/github/
+ exec: |
+ DEBIAN_FRONTEND=noninteractive sudo apt update
+ DEBIAN_FRONTEND=noninteractive sudo apt install -y ruby build-essential autoconf libssl-dev libyaml-dev zlib1g-dev libgmp-dev libffi-dev
+
+ - name: Check out the repository
+ uses: Ubuntu/WSL/.github/actions/wsl-checkout@main
+ with:
+ distro: Ubuntu-24.04
+ working-dir: /tmp/github/
+ submodules: true
+
+ - name: Build
+ uses: Ubuntu/WSL/.github/actions/wsl-bash@main
+ with:
+ distro: Ubuntu-24.04
+ working-dir: /tmp/github/
+ exec: |
+ ./autogen.sh
+ ./configure --disable-install-doc
+ make ruby -j4
+ make extract-gems
+ make -j4
+
+ - name: Test
+ uses: Ubuntu/WSL/.github/actions/wsl-bash@main
+ with:
+ distro: Ubuntu-24.04
+ working-dir: /tmp/github/
+ exec: |
+ ./ruby -v
+ # make check TESTS="-j4" MSPECOPT="-j"
diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml
new file mode 100644
index 0000000000..a59b4d6508
--- /dev/null
+++ b/.github/workflows/yjit-macos.yml
@@ -0,0 +1,198 @@
+name: YJIT macOS
+on:
+ push:
+ branches:
+ - master
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ cargo:
+ name: cargo test
+
+ runs-on: macos-14
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - run: RUST_BACKTRACE=1 cargo test
+ working-directory: yjit
+
+ # Also compile and test with all features enabled
+ - run: RUST_BACKTRACE=1 cargo test --all-features
+ working-directory: yjit
+
+ # Check that we can build in release mode too
+ - run: cargo build --release
+ working-directory: yjit
+
+ make:
+ strategy:
+ matrix:
+ include:
+ - test_task: 'check'
+ configure: '--enable-yjit'
+ yjit_opts: '--yjit'
+ - test_task: 'check'
+ configure: '--enable-yjit=dev'
+ yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc'
+ specopts: '-T --yjit-call-threshold=1 -T --yjit-verify-ctx -T --yjit-code-gc'
+ fail-fast: false
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUN_OPTS: ${{ matrix.yjit_opts }}
+ SPECOPTS: ${{ matrix.specopts }}
+
+ runs-on: macos-14
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - name: Install libraries
+ uses: ./.github/actions/setup/macos
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
+
+ - run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+
+ - run: make
+
+ - name: Verify that --yjit-dump-disasm works
+ run: |
+ ./miniruby --yjit-call-threshold=1 --yjit-dump-disasm -e0 | \
+ wc -l | \
+ ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
+ if: ${{ contains(matrix.configure, 'jit=dev') }}
+
+ - name: Set ENV for YJIT
+ run: |
+ echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
+ echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV
+
+ - name: Set test options for skipped tests
+ run: |
+ set -x
+ TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')"
+ echo "TESTS=${TESTS}" >> $GITHUB_ENV
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+
+ - name: Set up Launchable
+ id: launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: macos-14
+ test-opts: ${{ matrix.configure }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ is-yjit: true
+ continue-on-error: true
+ timeout-minutes: 3
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ set -x
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \
+ RUN_OPTS="$RUN_OPTS" \
+ SPECOPTS="$SPECOPTS"
+ timeout-minutes: 60
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ SYNTAX_SUGGEST_TIMEOUT: '5'
+ PRECHECK_BUNDLED_GEMS: 'no'
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
+ continue-on-error: ${{ matrix.continue-on-test_task || false }}
+
+ - name: make skipped tests
+ run: |
+ make -s test-all TESTS="${TESTS//-n!\//-n/}"
+ env:
+ GNUMAKEFLAGS: ''
+ RUBY_TESTOPTS: '-v --tty=no'
+ PRECHECK_BUNDLED_GEMS: 'no'
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+
+ - name: Dump crash logs
+ if: ${{ failure() }}
+ continue-on-error: true
+ run: |
+ tail --verbose --lines=+1 rb_crash_*.txt
+ exit 1
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }} ${{ matrix.yjit_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: macos-14
+ needs: [make]
+ steps:
+ - name: ${{ github.workflow }} jobs have failed
+ run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml
new file mode 100644
index 0000000000..150f0b3275
--- /dev/null
+++ b/.github/workflows/yjit-ubuntu.yml
@@ -0,0 +1,240 @@
+name: YJIT Ubuntu
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ cargo:
+ name: cargo test
+
+ # GitHub Action's image seems to already contain a Rust 1.58.0.
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ # For now we can't run cargo test --offline because it complains about the
+ # capstone dependency, even though the dependency is optional
+ #- run: cargo test --offline
+
+ - run: RUST_BACKTRACE=1 cargo test
+ working-directory: yjit
+
+ # Also compile and test with all features enabled
+ - run: RUST_BACKTRACE=1 cargo test --all-features
+ working-directory: yjit
+
+ # Check that we can build in release mode too
+ - run: cargo build --release
+ working-directory: yjit
+
+ lint:
+ name: cargo clippy
+
+ # GitHub Action's image seems to already contain a Rust 1.58.0.
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ # Check that we don't have linting errors in release mode, too
+ - run: cargo clippy --all-targets --all-features
+ working-directory: yjit
+
+ make:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - test_task: 'yjit-bindgen'
+ hint: 'To fix: use patch in logs'
+ # Build with YJIT+ZJIT for output that works in the most number of configurations
+ configure: '--with-gcc=clang-14 --enable-yjit=dev --enable-zjit'
+ libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1'
+
+ - test_task: 'check'
+ # YJIT should be automatically built in release mode on x86-64 Linux with rustc present
+ #configure: "--enable-yjit RUSTC='rustc +1.58.0'"
+ configure: "RUSTC='rustc +1.58.0'"
+ rust_version: '1.58.0'
+
+ - test_task: 'check'
+ configure: '--enable-yjit=dev'
+
+ - test_task: 'check'
+ configure: '--enable-yjit=dev'
+ yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc'
+ specopts: '-T --yjit-call-threshold=1 -T --yjit-verify-ctx -T --yjit-code-gc'
+
+ - test_task: 'test-bundled-gems'
+ configure: '--enable-yjit=dev'
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUN_OPTS: ${{ matrix.yjit_opts }}
+ YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }}
+ SPECOPTS: ${{ matrix.specopts }}
+ RUBY_DEBUG: ci
+ RUST_BACKTRACE: 1
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: Install Rust
+ if: ${{ matrix.rust_version }}
+ run: rustup install ${{ matrix.rust_version }} --profile minimal
+
+ - name: Remove cargo
+ # Since this tests a `rustc` build for release, remove `cargo` to ensure
+ # that only `rustc` is used.
+ if: ${{ contains(matrix.configure, 'rustc') }}
+ run: sudo rm $(which -a cargo | uniq)
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }}
+
+ - run: make incs
+
+ - run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+
+ - run: make
+
+ - name: Verify that --yjit-dump-disasm works
+ run: |
+ ./miniruby --yjit-call-threshold=1 --yjit-dump-disasm -e0 | \
+ wc -l | \
+ ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
+ if: ${{ contains(matrix.configure, 'jit=dev') }}
+
+ - name: Set ENV for YJIT
+ run: |
+ echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
+ echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV
+
+ # Check that the binary was built with YJIT
+ - name: Check YJIT enabled
+ run: ./miniruby --yjit -v | grep "+YJIT"
+
+ - name: Set up Launchable
+ id: launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ubuntu-22.04
+ test-opts: ${{ matrix.configure }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ is-yjit: true
+ continue-on-error: true
+ timeout-minutes: 3
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ set -x
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \
+ RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS" \
+ YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS"
+ timeout-minutes: 90
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ PRECHECK_BUNDLED_GEMS: 'no'
+ SYNTAX_SUGGEST_TIMEOUT: '5'
+ YJIT_BINDGEN_DIFF_OPTS: '--exit-code'
+ LIBCLANG_PATH: ${{ matrix.libclang_path }}
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
+ continue-on-error: ${{ matrix.continue-on-test_task || false }}
+
+ - name: Dump crash logs
+ if: ${{ failure() }}
+ continue-on-error: true
+ run: |
+ tail --verbose --lines=+1 rb_crash_*.txt
+ exit 1
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: ubuntu-latest
+ needs: [make]
+ steps:
+ - run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml
new file mode 100644
index 0000000000..a638907811
--- /dev/null
+++ b/.github/workflows/zjit-macos.yml
@@ -0,0 +1,214 @@
+name: ZJIT macOS
+on:
+ push:
+ branches:
+ - master
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - test_task: 'check'
+ run_opts: '--zjit-call-threshold=1'
+ specopts: '-T --zjit-call-threshold=1'
+ configure: '--enable-zjit=dev'
+
+ - test_task: 'check'
+ run_opts: '--zjit-disable-hir-opt --zjit-call-threshold=1'
+ specopts: '-T --zjit-disable-hir-opt -T --zjit-call-threshold=1'
+ configure: '--enable-zjit=dev'
+
+ - test_task: 'zjit-check' # zjit-test + quick feedback of test_zjit.rb
+ configure: '--enable-yjit=dev --enable-zjit'
+ rust_version: "1.85.0"
+
+ - test_task: 'ruby'
+ hint: 'combo build test'
+ configure: '--enable-yjit --enable-zjit'
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUN_OPTS: ${{ matrix.run_opts }}
+ SPECOPTS: ${{ matrix.specopts }}
+ TESTOPTS: ${{ matrix.testopts }}
+ ZJIT_RB_BUG: 1
+
+ runs-on: macos-14
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - name: Install libraries
+ uses: ./.github/actions/setup/macos
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: Install Rust
+ if: ${{ matrix.rust_version }}
+ run: |
+ rustup install ${{ matrix.rust_version }} --profile minimal
+ rustup default ${{ matrix.rust_version }}
+
+ - uses: taiki-e/install-action@v2
+ with:
+ tool: nextest@0.9
+ if: ${{ matrix.test_task == 'zjit-check' }}
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
+
+ - run: make
+
+ - name: Verify that --zjit-dump-disasm works
+ run: |
+ ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e0 | \
+ wc -l | \
+ ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
+ if: ${{ contains(matrix.configure, 'jit=dev') }}
+
+ - name: Set ENV for ZJIT
+ run: |
+ echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ set -x
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \
+ RUN_OPTS="$RUN_OPTS" \
+ SPECOPTS="$SPECOPTS" \
+ TESTOPTS="$TESTOPTS"
+ timeout-minutes: 60
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ EXCLUDES: '../src/test/.excludes-zjit'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ SYNTAX_SUGGEST_TIMEOUT: '5'
+ PRECHECK_BUNDLED_GEMS: 'no'
+ continue-on-error: ${{ matrix.continue-on-test_task || false }}
+
+ - name: Dump crash logs
+ if: ${{ failure() }}
+ continue-on-error: true
+ run: |
+ tail --verbose --lines=+1 rb_crash_*.txt
+ exit 1
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: macos-14
+ needs: [make]
+ steps:
+ - run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+ # Separated from `make` job to avoid making it a required status check for now
+ ruby-bench:
+ strategy:
+ matrix:
+ include:
+ # Test --call-threshold=2 with 2 iterations in total
+ - ruby_opts: '--zjit-call-threshold=2'
+ bench_opts: '--warmup=1 --bench=1 --excludes=lobsters'
+ configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow
+
+ runs-on: macos-14
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ./.github/actions/setup/macos
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install" ${{ matrix.configure }}
+
+ - run: make install
+
+ # setup/directories set MAKEFLAGS=-j4 for macOS, which randomly fails sqlite3.gem builds
+ - name: Unset MAKEFLAGS
+ run: echo "MAKEFLAGS=" >> "$GITHUB_ENV"
+
+ - name: Checkout ruby-bench
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ repository: ruby/ruby-bench
+ path: ruby-bench
+
+ # If you want to skip failing benchmark, consider using `--excludes`.
+ # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'`
+ - name: Run ruby-bench
+ run: ruby run_benchmarks.rb -e "zjit::../build/install/bin/ruby ${{ matrix.ruby_opts }}" ${{ matrix.bench_opts }}
+ working-directory: ruby-bench
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml
new file mode 100644
index 0000000000..28bfec963e
--- /dev/null
+++ b/.github/workflows/zjit-ubuntu.yml
@@ -0,0 +1,267 @@
+name: ZJIT Ubuntu
+on:
+ push:
+ branches:
+ - master
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ lint:
+ name: cargo clippy
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - run: cargo clippy --all-targets --all-features
+ working-directory: zjit
+
+ make:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - test_task: 'check'
+ run_opts: '--zjit-call-threshold=1'
+ specopts: '-T --zjit-call-threshold=1'
+ configure: '--enable-zjit=dev'
+
+ - test_task: 'check'
+ run_opts: '--zjit-disable-hir-opt --zjit-call-threshold=1'
+ specopts: '-T --zjit-disable-hir-opt -T --zjit-call-threshold=1'
+ configure: '--enable-zjit=dev'
+
+ # The optimizer benefits from at least 1 iteration of profiling. Also, many
+ # regression tests in bootstraptest/test_yjit.rb assume call-threshold=2.
+ - test_task: 'btest'
+ run_opts: '--zjit-call-threshold=2'
+ configure: '--enable-zjit=dev'
+
+ - test_task: 'zjit-check' # zjit-test + quick feedback of test_zjit.rb
+ configure: '--enable-yjit --enable-zjit=dev'
+ rust_version: '1.85.0'
+
+ - test_task: 'zjit-bindgen'
+ hint: 'To fix: use patch in logs'
+ # Build with YJIT+ZJIT for output that works in the most number of configurations
+ configure: '--enable-zjit=dev --enable-yjit --with-gcc=clang-16'
+ clang_path: '/usr/bin/clang-16'
+ runs-on: 'ubuntu-24.04' # for clang-16
+
+ - test_task: 'test-bundled-gems'
+ configure: '--enable-zjit=dev'
+ run_opts: '--zjit-call-threshold=1'
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUN_OPTS: ${{ matrix.run_opts }}
+ YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }}
+ SPECOPTS: ${{ matrix.specopts }}
+ TESTOPTS: ${{ matrix.testopts }}
+ RUBY_DEBUG: ci
+ BUNDLE_JOBS: 8 # for yjit-bench
+ RUST_BACKTRACE: 1
+ ZJIT_RB_BUG: 1
+
+ runs-on: ${{ matrix.runs-on || 'ubuntu-22.04' }}
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+
+ - uses: taiki-e/install-action@v2
+ with:
+ tool: nextest@0.9
+ if: ${{ matrix.test_task == 'zjit-check' }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: Install Rust
+ if: ${{ matrix.rust_version }}
+ run: |
+ rustup install ${{ matrix.rust_version }} --profile minimal
+ rustup default ${{ matrix.rust_version }}
+
+ - name: Install rustfmt
+ if: ${{ matrix.test_task == 'zjit-bindgen' }}
+ run: rustup component add rustfmt
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }}
+
+ - run: make incs
+
+ - run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+
+ - run: make
+
+ - name: Verify that --zjit-dump-disasm works
+ run: |
+ ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e0 | \
+ wc -l | \
+ ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
+ if: ${{ contains(matrix.configure, 'jit=dev') }}
+
+ # Check that the binary was built with ZJIT
+ - name: Check ZJIT enabled
+ run: ./miniruby --zjit -v | grep "+ZJIT"
+ if: ${{ matrix.configure != '--disable-zjit' }}
+
+ - name: Set ENV for ZJIT
+ run: |
+ echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ set -x
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \
+ RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS" \
+ TESTOPTS="$TESTOPTS" \
+ ZJIT_BINDGEN_DIFF_OPTS="$ZJIT_BINDGEN_DIFF_OPTS"
+ timeout-minutes: 90
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ EXCLUDES: '../src/test/.excludes-zjit'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ PRECHECK_BUNDLED_GEMS: 'no'
+ SYNTAX_SUGGEST_TIMEOUT: '5'
+ ZJIT_BINDGEN_DIFF_OPTS: '--exit-code'
+ CLANG_PATH: ${{ matrix.clang_path }}
+ continue-on-error: ${{ matrix.continue-on-test_task || false }}
+
+ - name: Dump crash logs
+ if: ${{ failure() }}
+ continue-on-error: true
+ run: |
+ tail --verbose --lines=+1 rb_crash_*.txt
+ exit 1
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: ubuntu-22.04
+ needs: [make]
+ steps:
+ - name: ${{ github.workflow }} jobs have failed
+ run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+ # Separated from `make` job to avoid making it a required status check for now
+ ruby-bench:
+ strategy:
+ matrix:
+ include:
+ # Test --call-threshold=2 with 2 iterations in total
+ - ruby_opts: '--zjit-call-threshold=2'
+ bench_opts: '--warmup=1 --bench=1 --excludes=lobsters'
+ configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow
+
+ runs-on: ubuntu-24.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install" ${{ matrix.configure }}
+
+ - run: make install
+
+ - name: Checkout ruby-bench
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ repository: ruby/ruby-bench
+ path: ruby-bench
+
+ # If you want to skip failing benchmark, consider using `--excludes`.
+ # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'`
+ - name: Run ruby-bench
+ run: ruby run_benchmarks.rb -e "zjit::../build/install/bin/ruby ${{ matrix.ruby_opts }}" ${{ matrix.bench_opts }}
+ working-directory: ruby-bench
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build