diff options
Diffstat (limited to '.github/workflows')
41 files changed, 3625 insertions, 916 deletions
diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml index 25454f6abe..1d23c38fcd 100644 --- a/.github/workflows/annocheck.yml +++ b/.github/workflows/annocheck.yml @@ -4,7 +4,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,19 +12,12 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -35,7 +28,7 @@ permissions: jobs: compile: - name: gcc-11 annocheck + name: test-annocheck runs-on: ubuntu-latest @@ -48,7 +41,7 @@ jobs: || 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} env: @@ -68,10 +61,11 @@ jobs: - run: id working-directory: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + persist-credentials: false - uses: ./.github/actions/setup/directories with: @@ -79,6 +73,11 @@ jobs: builddir: build makeup: true + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.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 @@ -100,22 +99,7 @@ jobs: - run: make - - run: make test - - - run: make install - - - run: make test-tool - - ### test-all doesn't work: https://github.com/ruby/ruby/actions/runs/4340112185/jobs/7578344307 - # - run: make test-all TESTS='-- ruby -ext-' - - ### test-spec doesn't work: https://github.com/ruby/ruby/actions/runs/4340193212/jobs/7578505652 - # - run: make test-spec - # env: - # CHECK_LEAKS: true - - run: make test-annocheck - continue-on-error: true # toomanyrequests: You have reached your pull rate limit. - uses: ./.github/actions/slack with: diff --git a/.github/workflows/auto_request_review.yml b/.github/workflows/auto_request_review.yml index 998a6ea58a..1be2b11b86 100644 --- a/.github/workflows/auto_request_review.yml +++ b/.github/workflows/auto_request_review.yml @@ -2,6 +2,7 @@ name: Auto Request Review on: pull_request_target: types: [opened, ready_for_review, reopened] + branches: [master] permissions: contents: read @@ -13,7 +14,7 @@ jobs: 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@6a51cebffe2c084705d9a7b394abd802e0119633 # v0.12.0 + uses: necojackarc/auto-request-review@5d3060495e58e9cb41f51de50e808d3135d5374e # master with: # scope: public_repo - token: ${{ secrets.MATZBOT_GITHUB_TOKEN }} + 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..24859ad0b0 --- /dev/null +++ b/.github/workflows/auto_review_pr.yml @@ -0,0 +1,41 @@ +name: Auto Review PR +on: + pull_request_target: + types: [opened, ready_for_review, reopened] + branches: [master] + workflow_dispatch: + inputs: + pr_number: + description: 'PR number to review' + required: true + type: number + +permissions: + contents: read + +jobs: + auto-review-pr: + name: Auto Review PR + runs-on: ubuntu-latest + if: ${{ github.repository == 'ruby/ruby' && (github.base_ref == 'master' || github.event_name == 'workflow_dispatch') }} + + permissions: + pull-requests: write + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.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 || github.event.inputs.pr_number }} diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 860d74aa1a..1acfbe19ac 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -4,7 +4,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,19 +12,12 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -37,33 +30,32 @@ jobs: baseruby: name: BASERUBY - runs-on: ubuntu-20.04 + 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} strategy: matrix: ruby: - - ruby-2.5 -# - ruby-2.6 -# - ruby-2.7 - - ruby-3.0 - ruby-3.1 - ruby-3.2 + - ruby-3.3 steps: - - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 with: ruby-version: ${{ matrix.ruby }} bundler: none - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - uses: ./.github/actions/setup/ubuntu diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml index 943140e9ef..d890ed2495 100644 --- a/.github/workflows/bundled_gems.yml +++ b/.github/workflows/bundled_gems.yml @@ -1,5 +1,8 @@ name: bundled_gems +env: + UPDATE_ENABLED: true + on: push: branches: ['master'] @@ -12,10 +15,6 @@ on: - '.github/workflows/bundled_gems.yml' - 'gems/bundled_gems' merge_group: - branches: ['master'] - paths: - - '.github/workflows/bundled_gems.yml' - - 'gems/bundled_gems' schedule: - cron: '45 6 * * *' workflow_dispatch: @@ -35,13 +34,17 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # zizmor: ignore[artipacked] with: - token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + ruby-version: 4.0 - uses: ./.github/actions/setup/directories with: - # Skip overwriting MATZBOT_GITHUB_TOKEN + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) - name: Set ENV @@ -50,19 +53,23 @@ jobs: - name: Download previous gems list run: | - data=bundled_gems.json mkdir -p .downloaded-cache - ln -s .downloaded-cache/$data . - curl -O -R -z ./$data https://stdgems.org/$data + for data in bundled_gems.json default_gems.json; do + ln -s .downloaded-cache/$data . + curl --retry 5 --retry-connrefused --retry-delay 2 --retry-max-time 60 -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: Maintain updated gems list in NEWS run: | ruby tool/update-NEWS-gemlist.rb bundled + ruby tool/update-NEWS-github-release.rb --update + if: ${{ env.UPDATE_ENABLED == 'true' }} - name: Check diffs id: diff @@ -77,6 +84,67 @@ jobs: 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 }} @@ -102,27 +170,14 @@ jobs: TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' if: ${{ steps.diff.outputs.gems }} - - name: Commit + - name: Push run: | - git pull --ff-only origin ${GITHUB_REF#refs/heads/} - message="Update bundled gems list" - if [ -z "${gems}" ]; then - git commit --message="${message} at ${GITHUB_SHA:0:30} [ci skip]" - else - git commit --message="${message} as of ${TODAY}" - fi git push origin ${GITHUB_REF#refs/heads/} - 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: >- ${{ github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull') && - steps.diff.outputs.update + steps.commit.outcome == 'success' }} - uses: ./.github/actions/slack diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index 10c202c3c1..ad399b264f 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -3,27 +3,13 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - '.*.yml' pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -34,23 +20,19 @@ permissions: jobs: update-deps: + name: Dependency checks + strategy: matrix: - os: [ubuntu-20.04] + os: [ubuntu-latest] fail-fast: true 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.actor == 'dependabot[bot]') - )}} - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - uses: ./.github/actions/setup/ubuntu if: ${{ contains(matrix.os, 'ubuntu') }} @@ -60,14 +42,17 @@ jobs: - uses: ./.github/actions/setup/directories + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.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 all golf - - - run: ruby tool/update-deps --fix + - run: make fix-depends - - run: git diff --no-ext-diff --ignore-submodules --exit-code + - run: git diff --color --no-ext-diff --ignore-submodules --exit-code - uses: ./.github/actions/slack with: diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml index ce4397b35a..f194d00779 100644 --- a/.github/workflows/check_misc.yml +++ b/.github/workflows/check_misc.yml @@ -18,24 +18,49 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + ruby-version: head - uses: ./.github/actions/setup/directories with: makeup: true - # Skip overwriting MATZBOT_GITHUB_TOKEN + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) - - name: Check if C-sources are US-ASCII + - name: Re-generate Makefiles + run: | + # config.status needs to run as a shell script + { echo ':&&exit'; cat tool/prereq.status; } > config.status + : # same as actions/setup/directories/action.yml + for mk in Makefile GNUmakefile; do + sed -f tool/prereq.status template/$mk.in > $mk + done + + - name: Check for code styles run: | - grep -r -n --include='*.[chyS]' --include='*.asm' $'[^\t-~]' -- . && exit 1 || : + 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 trailing spaces + - name: Check if date in man pages is up-to-date run: | - git grep -I -n $'[\t ]$' -- '*.rb' '*.[chy]' '*.rs' '*.yml' && exit 1 || : - git grep -n $'^[\t ][\t ]*$' -- '*.md' && exit 1 || : + git fetch origin --depth=1 "${GITHUB_OLD_SHA}" + git diff --exit-code --name-only "${GITHUB_OLD_SHA}" HEAD -- man || + make V=1 GIT=git BASERUBY=ruby update-man-date + git diff --color --no-ext-diff --ignore-submodules --exit-code -- man + env: + GITHUB_OLD_SHA: ${{ github.event.pull_request.base.sha }} + if: ${{ startsWith(github.event_name, 'pull') }} - name: Check for bash specific substitution in configure.ac run: | @@ -52,65 +77,74 @@ jobs: exit $fail working-directory: include - - id: gems - run: true - if: ${{ github.ref == 'refs/heads/master' }} - - - name: Download previous gems list + - id: now 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' }} + date +"mon=%-m"%n"day=%-d" >> $GITHUB_OUTPUT + env: + TZ: Asia/Tokyo - - name: Make default gems list + - id: deprecation 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 + 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: | - ruby tool/update-NEWS-gemlist.rb default - if: ${{ steps.gems.outcome == 'success' }} + set -- $(sed 's/#.*//;/^rdoc /!d' gems/bundled_gems) + { echo version=$2; echo ref=$4; } >> $GITHUB_OUTPUT + + - name: Checkout rdoc + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: ruby/rdoc + ref: ${{ steps.rdoc.outputs.ref }} + path: .bundle/gems/rdoc-${{ steps.rdoc.outputs.version }} + persist-credentials: false + if: ${{ steps.rdoc.outputs.ref != '' }} - - name: Check diffs - id: diff + - name: Generate rdoc scripts + 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: | - git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md || - echo update=true >> $GITHUB_OUTPUT - if: ${{ steps.gems.outcome == 'success' }} + make XRUBY=ruby RDOC_DEPENDS= RBCONFIG=update-rbconfig rdoc-coverage - - name: Commit + - name: Generate docs + id: docs 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 + make XRUBY=ruby RDOC_DEPENDS= RBCONFIG=update-rbconfig HTMLOUT=html html + echo htmlout=ruby-html-${GITHUB_SHA:0:10} >> $GITHUB_OUTPUT + # Generate only when document commit/PR if: >- - ${{ - github.repository == 'ruby/ruby' && - !startsWith(github.event_name, 'pull') && - steps.diff.outputs.update + ${{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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + 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 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/check_sast.yml index 47104672fe..6fd1be6542 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/check_sast.yml @@ -1,11 +1,11 @@ -name: 'CodeQL' +name: 'Check SAST tool' on: push: branches: ['master'] paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -13,7 +13,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -30,63 +30,69 @@ permissions: # added using https://github.com/step-security/secure-workflows contents: read jobs: + zizmor: + name: zizmor + + runs-on: ubuntu-latest + + permissions: + contents: read + security-events: write + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Run zizmor + uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 + continue-on-error: true + 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 + security-events: write # for github/codeql-action/upload-sarif 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} - env: - enable_install_doc: no - strategy: fail-fast: false matrix: - language: ['cpp', 'ruby'] + include: + - language: cpp + - language: ruby steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Install libraries - uses: ./.github/actions/setup/ubuntu - - - uses: ./.github/actions/setup/directories - - - name: Remove an obsolete rubygems vendored file - run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: languages: ${{ matrix.language }} - - - name: Autobuild - uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + build-mode: none + config-file: .github/codeql/codeql-config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: category: '/language:${{ matrix.language }}' upload: False output: sarif-results - ram: 8192 - # CodeQL randomly hits `OutOfMemoryError "Java heap space"`. - # GitHub recommends running a larger runner to fix it, but we don't pay for it. - continue-on-error: true - name: filter-sarif - uses: advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d # v1.0 + uses: advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1 with: patterns: | +**/*.rb @@ -94,6 +100,7 @@ jobs: -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 + -spec/ruby/core/regexp/timeout_spec.rb:rb/redos -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 @@ -108,8 +115,19 @@ jobs: if: ${{ matrix.language == 'ruby' }} continue-on-error: true + - name: filter-sarif + uses: advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1 + with: + patterns: | + +**/*.c + +**/*.h + input: sarif-results/${{ matrix.language }}.sarif + output: sarif-results/${{ matrix.language }}.sarif + if: ${{ matrix.language == 'cpp' }} + continue-on-error: true + - name: Upload SARIF - uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: sarif_file: sarif-results/${{ matrix.language }}.sarif continue-on-error: true diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml index 233f4c5db3..147470f38a 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -1,10 +1,11 @@ +# 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' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,284 +13,320 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} -# GitHub actions does not support YAML anchors. This creative use of -# environment variables (plus the "echo $GITHUB_ENV" hack) is to reroute that -# restriction. -env: - default_cc: clang-17 - append_cc: '' - - # -O1 is faster than -O3 in our tests... Majority of time are consumed trying - # to optimize binaries. Also GitHub Actions run on relatively modern CPUs - # compared to, say, GCC 4 or Clang 3. We don't specify `-march=native` - # because compilers tend not understand what the CPU is. - optflags: '-O1' - - # -g0 disables backtraces when SEGV. Do not set that. - debugflags: '-ggdb3' - - default_configure: >- - --enable-debug-env - --disable-install-doc - --with-ext=-test-/cxxanyargs,+ - append_configure: >- - --without-valgrind - --without-jemalloc - --without-gmp - - CONFIGURE_TTY: never - GITPULLOPTIONS: --no-tags origin ${{ github.ref }} - RUBY_DEBUG: ci rgengc - RUBY_TESTOPTS: >- - -q - --color=always - --tty=no - permissions: contents: read +# Each job is split so that they roughly take 30min to run through. jobs: - compile: - strategy: - fail-fast: false - matrix: - env: - - {} - entry: - - { name: gcc-13, env: { default_cc: gcc-13 } } - - { name: gcc-12, env: { default_cc: gcc-12 } } - - { name: gcc-11, env: { default_cc: gcc-11 } } - - { name: gcc-10, env: { default_cc: gcc-10 } } - - { name: gcc-9, env: { default_cc: gcc-9 } } - - { name: gcc-8, env: { default_cc: gcc-8 } } - - { name: gcc-7, env: { default_cc: gcc-7 } } - - name: 'gcc-13 LTO' - container: gcc-13 - env: - default_cc: 'gcc-13 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch' - optflags: '-O2' - shared: disable - # check: true - - { name: clang-18, env: { default_cc: clang-18 } } - - { name: clang-17, env: { default_cc: clang-17 } } - - { name: clang-16, env: { default_cc: clang-16 } } - - { name: clang-15, env: { default_cc: clang-15 } } - - { name: clang-14, env: { default_cc: clang-14 } } - - { name: clang-13, env: { default_cc: clang-13 } } - - { name: clang-12, env: { default_cc: clang-12 } } - - { name: clang-11, env: { default_cc: clang-11 } } - - { name: clang-10, env: { default_cc: clang-10 } } - # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o. - - { name: clang-9, env: { default_cc: clang-9, append_configure: '--disable-yjit' } } - - { name: clang-8, env: { default_cc: clang-8, append_configure: '--disable-yjit' } } - - { name: clang-7, env: { default_cc: clang-7, append_configure: '--disable-yjit' } } - - { name: clang-6.0, env: { default_cc: clang-6.0, append_configure: '--disable-yjit' } } - - name: 'clang-16 LTO' - container: clang-16 - env: - default_cc: 'clang-16 -flto=auto' - optflags: '-O2' - shared: disable - # check: true - - - { name: ext/Setup } - -# - { name: aarch64-linux-gnu, crosshost: aarch64-linux-gnu, container: crossbuild-essential-arm64 } -# - { name: arm-linux-gnueabi, crosshost: arm-linux-gnueabi } -# - { name: arm-linux-gnueabihf, crosshost: arm-linux-gnueabihf } -# - { name: i686-w64-mingw32, crosshost: i686-w64-mingw32 } -# - { name: powerpc-linux-gnu, crosshost: powerpc-linux-gnu } -# - { name: powerpc64le-linux-gnu, crosshost: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el } -# - { name: s390x-linux-gnu, crosshost: s390x-linux-gnu, container: crossbuild-essential-s390x } -# - { name: x86_64-w64-mingw32, crosshost: x86_64-w64-mingw32, container: mingw-w64 } - - # -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 - - { name: c99, env: { CFLAGS: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } -# - { name: c11, env: { CFLAGS: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } -# - { name: c17, env: { CFLAGS: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } - - { name: c23, env: { CFLAGS: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } - - { name: c++98, env: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++11, env: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++14, env: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++17, env: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++20, env: { CXXFLAGS: '-std=c++20 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++23, env: { CXXFLAGS: '-std=c++23 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } - - { name: c++26, env: { CXXFLAGS: '-std=c++26 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } - - - { name: '-O0', env: { optflags: '-O0 -march=x86-64 -mtune=generic' } } -# - { name: '-O3', env: { optflags: '-O3 -march=x86-64 -mtune=generic' }, check: true } - - - { name: gmp, env: { append_configure: '--with-gmp' } } - - { name: jemalloc, env: { append_configure: '--with-jemalloc' } } - - { name: valgrind, env: { append_configure: '--with-valgrind' } } - - { name: 'coroutine=ucontext', env: { append_configure: '--with-coroutine=ucontext' } } - - { name: 'coroutine=pthread', env: { append_configure: '--with-coroutine=pthread' } } - - { name: disable-jit, env: { append_configure: '--disable-yjit --disable-rjit' } } - - { name: disable-dln, env: { append_configure: '--disable-dln' } } - - { name: enable-mkmf-verbose, env: { append_configure: '--enable-mkmf-verbose' } } - - { name: disable-rubygems, env: { append_configure: '--disable-rubygems' } } - - { name: RUBY_DEVEL, env: { append_configure: '--enable-devel' } } - - - { name: OPT_THREADED_CODE=1, env: { cppflags: '-DOPT_THREADED_CODE=1' } } - - { name: OPT_THREADED_CODE=2, env: { cppflags: '-DOPT_THREADED_CODE=2' } } - - { name: OPT_THREADED_CODE=3, env: { cppflags: '-DOPT_THREADED_CODE=3' } } - - - { name: NDEBUG, env: { cppflags: '-DNDEBUG' } } - - { name: RUBY_DEBUG, env: { cppflags: '-DRUBY_DEBUG' } } -# - { name: ARRAY_DEBUG, env: { cppflags: '-DARRAY_DEBUG' } } -# - { name: BIGNUM_DEBUG, env: { cppflags: '-DBIGNUM_DEBUG' } } -# - { name: CCAN_LIST_DEBUG, env: { cppflags: '-DCCAN_LIST_DEBUG' } } -# - { name: CPDEBUG=-1, env: { cppflags: '-DCPDEBUG=-1' } } -# - { name: ENC_DEBUG, env: { cppflags: '-DENC_DEBUG' } } -# - { name: GC_DEBUG, env: { cppflags: '-DGC_DEBUG' } } -# - { name: HASH_DEBUG, env: { cppflags: '-DHASH_DEBUG' } } -# - { name: ID_TABLE_DEBUG, env: { cppflags: '-DID_TABLE_DEBUG' } } -# - { name: RGENGC_DEBUG=-1, env: { cppflags: '-DRGENGC_DEBUG=-1' } } -# - { name: SYMBOL_DEBUG, env: { cppflags: '-DSYMBOL_DEBUG' } } - -# - { name: RGENGC_CHECK_MODE, env: { cppflags: '-DRGENGC_CHECK_MODE' } } -# - { name: VM_CHECK_MODE, env: { cppflags: '-DVM_CHECK_MODE' } } - -# - { name: USE_EMBED_CI=0, env: { cppflags: '-DUSE_EMBED_CI=0' } } - - name: USE_FLONUM=0 - env: - cppflags: '-DUSE_FLONUM=0' - # yjit requires FLONUM for the pointer tagging scheme - append_configure: '--disable-yjit' -# - { name: USE_GC_MALLOC_OBJ_INFO_DETAILS, env: { cppflags: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' } } -# - { name: USE_LAZY_LOAD, env: { cppflags: '-DUSE_LAZY_LOAD' } } -# - { name: USE_SYMBOL_GC=0, env: { cppflags: '-DUSE_SYMBOL_GC=0' } } -# - { name: USE_THREAD_CACHE=0, env: { cppflags: '-DUSE_THREAD_CACHE=0' } } - - { name: USE_RUBY_DEBUG_LOG=1, env: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' } } -# - { name: USE_DEBUG_COUNTER, env: { cppflags: '-DUSE_DEBUG_COUNTER=1', RUBY_DEBUG_COUNTER_DISABLE: '1' } } - - { name: SHARABLE_MIDDLE_SUBSTRING, env: { cppflags: '-DSHARABLE_MIDDLE_SUBSTRING=1' } } - -# - { name: DEBUG_FIND_TIME_NUMGUESS, env: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' } } -# - { name: DEBUG_INTEGER_PACK, env: { cppflags: '-DDEBUG_INTEGER_PACK' } } -# - { name: ENABLE_PATH_CHECK, env: { cppflags: '-DENABLE_PATH_CHECK' } } - -# - { name: GC_DEBUG_STRESS_TO_CLASS, env: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' } } -# - { name: GC_ENABLE_LAZY_SWEEP=0, env: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' } } -# - { name: GC_PROFILE_DETAIL_MEMOTY, env: { cppflags: '-DGC_PROFILE_DETAIL_MEMOTY' } } -# - { name: GC_PROFILE_MORE_DETAIL, env: { cppflags: '-DGC_PROFILE_MORE_DETAIL' } } - -# - { name: CALC_EXACT_MALLOC_SIZE, env: { cppflags: '-DCALC_EXACT_MALLOC_SIZE' } } -# - { name: MALLOC_ALLOCATED_SIZE_CHECK, env: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' } } - -# - { name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, env: { cppflags: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' } } - -# - { name: RGENGC_ESTIMATE_OLDMALLOC, env: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' } } -# - { name: RGENGC_FORCE_MAJOR_GC, env: { cppflags: '-DRGENGC_FORCE_MAJOR_GC' } } -# - { name: RGENGC_OBJ_INFO, env: { cppflags: '-DRGENGC_OBJ_INFO' } } -# - { name: RGENGC_PROFILE, env: { cppflags: '-DRGENGC_PROFILE' } } - -# - { name: VM_DEBUG_BP_CHECK, env: { cppflags: '-DVM_DEBUG_BP_CHECK' } } -# - { name: VM_DEBUG_VERIFY_METHOD_CACHE, env: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } } - - - { name: enable-yjit, env: { append_configure: '--enable-yjit --disable-rjit' } } - - { name: enable-rjit, env: { append_configure: '--enable-rjit --disable-yjit' } } - - { name: YJIT_FORCE_ENABLE, env: { cppflags: '-DYJIT_FORCE_ENABLE' } } -# - { name: RJIT_FORCE_ENABLE, env: { cppflags: '-DRJIT_FORCE_ENABLE' } } - - { name: UNIVERSAL_PARSER, env: { cppflags: '-DUNIVERSAL_PARSER' } } - - name: ${{ matrix.entry.name }} - + compile-if: + name: 'omnibus compilations, trigger' runs-on: ubuntu-latest - - container: - image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-17' }} - 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} - - env: ${{ matrix.entry.env || matrix.env }} - steps: - - run: id + - run: true working-directory: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - sparse-checkout-cone-mode: false - sparse-checkout: /.github + compile1: + name: 'omnibus compilations, #1' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 - - uses: ./.github/actions/setup/directories + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + # 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 22 LTO' + uses: './.github/actions/compilers' with: - srcdir: src - builddir: build - makeup: true + tag: clang-22 + with_gcc: 'clang-22 -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 - - name: Run configure - run: > - ../src/configure -C ${default_configure} ${append_configure} - --${{ - matrix.entry.crosshost && 'host' || 'with-gcc' - }}=${{ - matrix.entry.crosshost || '"${default_cc}${append_cc:+ $append_cc}"' - }} - --${{ matrix.entry.shared || 'enable' }}-shared + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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 } + + compile3: + name: 'omnibus compilations, #3' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 - - name: Add to ext/Setup # statically link just the etc extension - run: mkdir ext && echo etc >> ext/Setup - if: ${{ matrix.entry.name == 'ext/Setup' }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { 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 - - run: make showflags + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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 - - run: make + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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 - - run: make test + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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 - - run: make install - if: ${{ matrix.entry.check }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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 } + + compile8: + name: 'omnibus compilations, #8' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 - - run: make test-tool - if: ${{ matrix.entry.check }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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: '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 - - run: make test-all TESTS='-- ruby -ext-' - if: ${{ matrix.entry.check }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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 - - run: make test-spec - env: - CHECK_LEAKS: true - if: ${{ matrix.entry.check }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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_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 } + - { 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 } + - { uses: './.github/actions/compilers', name: 'clang 21', with: { tag: 'clang-21' }, timeout-minutes: 5 } + + compileB: + name: 'omnibus compilations, #11' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 - - run: make test-annocheck - if: ${{ matrix.entry.check && endsWith(matrix.entry.name, 'annocheck') }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } + - { 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 } + - { uses: './.github/actions/compilers', name: 'clang 23', with: { tag: 'clang-23' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 22', with: { tag: 'clang-22' }, 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 } + + 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false } - uses: ./.github/actions/slack with: - label: ${{ matrix.entry.name }} + label: 'omnibus' SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() }} + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + - run: false + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/crosscompile.yml b/.github/workflows/crosscompile.yml new file mode 100644 index 0000000000..4c28516e25 --- /dev/null +++ b/.github/workflows/crosscompile.yml @@ -0,0 +1,123 @@ +name: Cross compile +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 + 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: + name: make (${{ matrix.host }} host on ${{ matrix.build }}) + strategy: + matrix: + include: + - host: aarch64-linux-gnu + arch: arm64 + build: x86_64-linux-gnu + runs-on: ubuntu-24.04 + file_arch: ARM aarch64 + - host: x86_64-linux-gnu + arch: amd64 + build: aarch64-linux-gnu + runs-on: ubuntu-24.04-arm + file_arch: x86-64 + fail-fast: false + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + + runs-on: ${{ matrix.runs-on }} + + 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.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + persist-credentials: false + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + + - name: Setup cross-compilation toolchain sources + run: | + native_arch=$(dpkg --print-architecture) + # Restrict existing sources to native arch + sudo sed -i '/^Architectures:/d' /etc/apt/sources.list.d/ubuntu.sources + sudo sed -i "/^Types:/a Architectures: ${native_arch}" /etc/apt/sources.list.d/ubuntu.sources + # Add cross-arch sources + if [ "${{ matrix.arch }}" = "arm64" ]; then + cross_uri="http://ports.ubuntu.com/" + else + cross_uri="http://archive.ubuntu.com/ubuntu/" + fi + printf '%s\n' \ + "Types: deb" \ + "URIs: ${cross_uri}" \ + "Suites: noble noble-updates noble-security" \ + "Components: main universe" \ + "Architectures: ${{ matrix.arch }}" \ + | sudo tee /etc/apt/sources.list.d/cross-${{ matrix.arch }}.sources + + - uses: ./.github/actions/setup/ubuntu + with: + arch: ${{ matrix.arch }} + + - uses: ./.github/actions/setup/baseruby + id: baseruby + with: + srcdir: src + + - name: Run configure + run: >- + ../src/configure -C --disable-install-doc + --prefix=/usr + --build=${{ matrix.build }} + --host=${{ matrix.host }} + --with-baseruby="$baseruby" + env: + baseruby: ${{ steps.baseruby.outputs.ruby }} + + - run: make + + - run: make install DESTDIR=$PWD/install + + - name: Verify cross-compiled binary + run: | + file install/usr/bin/ruby + file install/usr/bin/ruby | grep -q '${{ matrix.file_arch }}' + + - uses: ./.github/actions/slack + with: + label: cross ${{ matrix.host }} + 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/cygwin.yml b/.github/workflows/cygwin.yml new file mode 100644 index 0000000000..5ab86c7b19 --- /dev/null +++ b/.github/workflows/cygwin.yml @@ -0,0 +1,75 @@ +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.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - run: git config --global core.autocrlf input + + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Setup Cygwin + uses: cygwin/cygwin-install-action@711d29f3da23c9f4a1798e369a6f01198c13b11a # v6.1 + with: + packages: ruby gcc-core make autoconf libtool libssl-devel libyaml-devel libffi-devel zlib-devel rubygems + site: | + https://cygwin.osuosl.org/ + + - 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..f52b83103c --- /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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # zizmor: ignore[artipacked] + 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 --retry 5 --retry-connrefused --retry-delay 2 --retry-max-time 60 -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 index 6259199b11..2e4dc8d7a2 100644 --- a/.github/workflows/dependabot_automerge.yml +++ b/.github/workflows/dependabot_automerge.yml @@ -1,23 +1,25 @@ # from https://github.com/gofiber/swagger/blob/main/.github/workflows/dependabot_automerge.yml name: Dependabot auto-merge on: - pull_request_target: + pull_request: + +permissions: + contents: write + pull-requests: write jobs: automerge: runs-on: ubuntu-latest - - if: ${{ github.actor == 'dependabot[bot]' }} - + if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'ruby/ruby' steps: - name: Dependabot metadata - uses: dependabot/fetch-metadata@c9c4182bf1b97f5224aee3906fd373f6b61b4526 # v1.6.0 + uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0 id: metadata - name: Wait for status checks - uses: lewagon/wait-on-check-action@e106e5c43e8ca1edea6383a39a01c5ca495fd812 # v1.3.1 + uses: lewagon/wait-on-check-action@9312864dfbc9fd208e9c0417843430751c042800 # v1.7.0 with: - repo-token: ${{ secrets.MATZBOT_GITHUB_TOKEN }} + repo-token: ${{ secrets.GITHUB_TOKEN }} ref: ${{ github.event.pull_request.head.sha || github.sha }} check-regexp: 'make \(check, .*\)' wait-interval: 30 @@ -27,4 +29,4 @@ jobs: run: gh pr merge --auto --rebase "$PR_URL" env: PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.MATZBOT_GITHUB_TOKEN }} + 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..d0a8024b05 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,15 @@ +name: "Pull Request Labeler" +on: +- pull_request_target + +permissions: + contents: read + +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0 diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 6411a02d2b..501d35698b 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,13 +12,6 @@ on: # 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: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -31,12 +24,31 @@ jobs: make: strategy: matrix: - test_task: ['check'] - configure: [''] - os: ${{ fromJSON(format('["macos-11","macos-12"{0}]', (github.repository == 'ruby/ruby' && ',"macos-arm-oss"' || ''))) }} include: - - test_task: test-all TESTS=--repeat-count=2 - os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-12' }} + - test_task: check + os: macos-26 + - test_task: check + os: macos-15 + configure_args: '--with-gcc=gcc-14' + - test_task: check + os: macos-26 + configure_args: '--with-jemalloc --with-opt-dir=$(brew --prefix jemalloc)' + - test_task: check + os: macos-26 + configure_args: '--with-gmp' + - test_task: test-all + test_opts: --repeat-count=2 + os: macos-26 + - test_task: test-bundler-parallel + os: macos-26 + - test_task: test-bundled-gems + os: macos-26 + - test_task: check + os: macos-15 + - test_task: check + os: macos-15-intel + - test_task: check + os: macos-14 fail-fast: false env: @@ -49,14 +61,15 @@ jobs: || 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + persist-credentials: false - name: Install libraries uses: ./.github/actions/setup/macos @@ -66,50 +79,111 @@ jobs: 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 ${{ matrix.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: | - make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`} - timeout-minutes: 60 + 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' - TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} 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=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'` + make -s test-all TESTS="${TESTS//-n!\//-n/}" env: GNUMAKEFLAGS: '' RUBY_TESTOPTS: '-v --tty=no' - TESTS: ${{ matrix.skipped_tests }} PRECHECK_BUNDLED_GEMS: 'no' - if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }} + 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 }} ${{ matrix.configure }} + label: ${{ matrix.os }} / ${{ matrix.test_task }} 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-latest + runs-on: ubuntu-latest needs: [make] steps: - run: exit 1 + working-directory: if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index df879f56b6..1efae8be59 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -3,30 +3,20 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - '.*.yml' - - '.*.yml' pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - '.*.yml' - - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -40,16 +30,32 @@ permissions: # jobs: make: - runs-on: windows-2022 + runs-on: windows-${{ matrix.os }} name: ${{ github.workflow }} (${{ matrix.msystem }}) env: MSYSTEM: ${{ matrix.msystem }} - MSYS2_ARCH: x86_64 - CHOST: 'x86_64-w64-mingw32' - CFLAGS: '-march=x86-64 -mtune=generic -O3 -pipe' - CXXFLAGS: '-march=x86-64 -mtune=generic -O3 -pipe' + MSYS2_ARCH: >- + ${{ case( + contains(matrix.msystem, 'arm64'), 'aarch64', + contains(matrix.msystem, '64'), 'x86_64', + 'i686' + ) }} + MINGW_PACKAGE_PREFIX: >- + mingw-w${{ + case(endsWith(matrix.msystem, '64'), '64', '32') + }}-${{ case( + startsWith(matrix.msystem, 'clang'), 'clang', + startsWith(matrix.msystem, 'ucrt'), 'ucrt', + 'mingw' + ) }}-${{ case( + 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 }} @@ -58,10 +64,14 @@ jobs: 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' - base_ruby: head + 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: >- @@ -69,69 +79,138 @@ jobs: || 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/vcpkg')) )}} steps: - - name: Set up Ruby & MSYS2 - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + - uses: msys2/setup-msys2@e9898307ac31d1a803454791be09ab9973336e1c # v2.31.1 + id: msys2 with: - ruby-version: ${{ matrix.base_ruby }} - - - name: where check - run: | - # show where - mv /c/Windows/System32/libcrypto-1_1-x64.dll /c/Windows/System32/libcrypto-1_1-x64.dll_ - mv /c/Windows/System32/libssl-1_1-x64.dll /c/Windows/System32/libssl-1_1-x64.dll_ - result=true - for e in gcc.exe ragel.exe make.exe libcrypto-1_1-x64.dll libssl-1_1-x64.dll; do - echo ::group::$'\033[93m'$e$'\033[m' - where $e || result=false - echo ::endgroup:: - done - $result + 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: - - - name: version check run: | - # show version - result=true - for e in gcc ragel make "openssl version"; do - case "$e" in *" "*) ;; *) e="$e --version";; esac - echo ::group::$'\033[93m'$e$'\033[m' - $e || result=false - echo ::endgroup:: - done - $result + $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 - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + persist-credentials: false - 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 + 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 - shell: cmd + run: make test test-tool env: GNUMAKEFLAGS: '' RUBY_TESTOPTS: '-v --tty=no' @@ -139,13 +218,13 @@ jobs: - name: test-all timeout-minutes: 45 - shell: cmd 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 + --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/') }} @@ -153,7 +232,6 @@ jobs: timeout-minutes: 10 run: | make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }} - shell: cmd if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/') }} - uses: ./src/.github/actions/slack @@ -165,4 +243,4 @@ jobs: defaults: run: working-directory: build - shell: sh + shell: cmd diff --git a/.github/workflows/modgc.yml b/.github/workflows/modgc.yml new file mode 100644 index 0000000000..bd3c6ab575 --- /dev/null +++ b/.github/workflows/modgc.yml @@ -0,0 +1,179 @@ +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-26, 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.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + persist-credentials: false + + - 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@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.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="${MODULAR_GC_DIR}" \ + ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} + + - uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.16.1 + with: + cache-bin: false + - 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/rjit.yml b/.github/workflows/parse_y.yml index bf9122f581..a0082f71de 100644 --- a/.github/workflows/rjit.yml +++ b/.github/workflows/parse_y.yml @@ -1,32 +1,22 @@ -name: RJIT +name: parse.y on: push: paths-ignore: - 'doc/**' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - - '**.[1-8]' - - '**.ronn' - '.*.yml' pull_request: paths-ignore: - 'doc/**' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - - '**.[1-8]' - - '**.ronn' - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**.md' - - '**.rdoc' - - '**/.document' - - '**.[1-8]' - - '**.ronn' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -39,10 +29,10 @@ jobs: make: strategy: matrix: - # main variables included in the job name - test_task: [check] - run_opts: ['--rjit-call-threshold=1'] - arch: [''] + include: + - test_task: check + - test_task: test-bundler-parallel + - test_task: test-bundled-gems fail-fast: false env: @@ -57,57 +47,48 @@ jobs: || 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + persist-credentials: false - uses: ./.github/actions/setup/ubuntu + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.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 - env: - arch: ${{ matrix.arch }} - run: >- - $SETARCH ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG - ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} + run: ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG --with-parser=parse.y - - run: $SETARCH make + - run: make - - name: make test - run: | - $SETARCH make -s test RUN_OPTS="$RUN_OPTS" - timeout-minutes: 30 + - run: make TESTRUN_SCRIPT='-renvutil -v -e "exit EnvUtil.current_parser == %[parse.y]"' run env: - GNUMAKEFLAGS: '' - RUBY_TESTOPTS: '-v --tty=no' - RUN_OPTS: ${{ matrix.run_opts }} - - - name: make test-all - run: | - $SETARCH make -s test-all RUN_OPTS="$RUN_OPTS" - timeout-minutes: 40 - env: - GNUMAKEFLAGS: '' - RUBY_TESTOPTS: '-q --tty=no' - RUN_OPTS: ${{ matrix.run_opts }} - - - name: make test-spec - run: | - $SETARCH make -s test-spec RUN_OPTS="$RUN_OPTS" - timeout-minutes: 10 + RUNOPT0: -I$(tooldir)/lib + + - name: make ${{ matrix.test_task }} + run: make -s ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" SPECOPTS="$SPECOPTS" env: - GNUMAKEFLAGS: '' - RUN_OPTS: ${{ matrix.run_opts }} + 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: diff --git a/.github/workflows/post_push.yml b/.github/workflows/post_push.yml new file mode 100644 index 0000000000..237679ebb1 --- /dev/null +++ b/.github/workflows/post_push.yml @@ -0,0 +1,97 @@ +name: Post-push +on: + push: + branches: + - master + - 'ruby_*_*' + +permissions: + contents: read + +jobs: + hooks: + name: Post-push hooks + runs-on: ubuntu-latest + if: ${{ github.repository == 'ruby/ruby' }} + steps: + - name: Sync git.ruby-lang.org + id: sync-git + continue-on-error: true + 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # zizmor: ignore[artipacked] + 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 + id: pr-notes + continue-on-error: true + 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' }} + + - name: Check for failures + run: exit 1 + if: ${{ steps.sync-git.outcome == 'failure' || steps.pr-notes.outcome == 'failure' }} + + - 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..dc4f075a38 --- /dev/null +++ b/.github/workflows/pr-playground.yml @@ -0,0 +1,131 @@ +name: Post Playground link to PR +on: + pull_request_target: + types: [labeled] + workflow_run: + workflows: ["WebAssembly"] + types: [completed] + +permissions: + contents: read + actions: read + +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@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.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..5d16915e10 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,114 @@ +name: Publish Ruby packages + +on: + repository_dispatch: + types: + - release + workflow_dispatch: + inputs: + version: + description: 'Version of the Ruby package to release' + required: true + default: '4.0.0' + +permissions: + contents: read + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + ruby-version: 3.3.4 + + - name: Store Ruby version + env: + RUBY_VERSION: ${{ github.event.client_payload.version || github.event.inputs.version }} + run: | + echo "RUBY_VERSION=${RUBY_VERSION}" >> $GITHUB_ENV + + - name: Store ABI version + run: echo "ABI_VERSION=$(echo ${RUBY_VERSION} | cut -d '.' -f 1-2)" >> $GITHUB_ENV + + - name: Copy draft package `/tmp` to `/pub` directory + run: tool/release.sh ${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/${ABI_VERSION}/ruby-${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/${ABI_VERSION}/ruby-${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/${ABI_VERSION}/ruby-${RUBY_VERSION}.zip + + - name: Create a release on GitHub + run: | + RELEASE_TAG=$(ruby tool/ruby-version.rb tag "${RUBY_VERSION}") + echo $RELEASE_TAG + PREVIOUS_RELEASE_TAG=$(ruby tool/ruby-version.rb previous-tag "${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/dispatches \ + -d "{\"event_type\": \"build\", \"client_payload\": {\"ruby_version\": \"${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\": \"${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\": \"${RUBY_VERSION}\", \"openssl_version\": \"${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..a35bcff99a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,21 @@ +name: Start release workflow +on: + push: + tags: + - '*' + +permissions: + contents: read + +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/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml deleted file mode 100644 index bf3c752e7b..0000000000 --- a/.github/workflows/rjit-bindgen.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: RJIT bindgen -on: - push: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' - pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' - merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' - -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: - - task: rjit-bindgen - fail-fast: false - - runs-on: ubuntu-20.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.actor == 'dependabot[bot]') - )}} - - steps: - - name: Set up Ruby - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 - with: - ruby-version: '3.1' - - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - sparse-checkout-cone-mode: false - sparse-checkout: /.github - - - 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 --enable-yjit=dev_nodebug - - - run: make - - - run: make install - - - run: make ${{ matrix.task }} - - - run: git diff --exit-code - working-directory: src - - - 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/rust-warnings.yml b/.github/workflows/rust-warnings.yml new file mode 100644 index 0000000000..23ed164405 --- /dev/null +++ b/.github/workflows/rust-warnings.yml @@ -0,0 +1,62 @@ +# 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.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - 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 index 51ce54a518..74c13f98fa 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -2,7 +2,7 @@ # by a third-party and are governed by separate terms of service, privacy # policy, and support documentation. -name: Scorecards supply-chain security +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 @@ -10,7 +10,7 @@ on: # To guarantee Maintained check is occasionally updated. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained schedule: - - cron: '22 4 * * 2' + - cron: '39 3 * * 5' # push: # branches: [ "master" ] @@ -19,8 +19,10 @@ permissions: read-all jobs: analysis: - name: Scorecards 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 @@ -31,21 +33,21 @@ jobs: # actions: read steps: - - name: 'Checkout code' - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: "Checkout code" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - name: 'Run analysis' - uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + - name: "Run analysis" + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif - # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if: + # (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 Scorecards on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. - repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} + # - 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 @@ -56,17 +58,21 @@ jobs: # 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@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - # with: - # name: SARIF file - # path: results.sarif - # retention-days: 5 + - name: "Upload artifact" + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: SARIF file + path: results.sarif + retention-days: 5 - # Upload the results to GitHub's code scanning dashboard. - - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.1.27 + # 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@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: sarif_file: results.sarif diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index e14e7818a6..856b6e434e 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -3,16 +3,15 @@ name: Rubyspec Version Guards Check on: push: paths: + - '.github/workflows/spec_guards.yml' - 'spec/**' - '!spec/*.md' pull_request: - paths-ignore: + paths: + - '.github/workflows/spec_guards.yml' - 'spec/**' - '!spec/*.md' merge_group: - paths-ignore: - - 'spec/**' - - '!spec/*.md' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -25,14 +24,14 @@ jobs: rubyspec: name: Rubyspec - runs-on: ubuntu-20.04 + 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} strategy: @@ -40,14 +39,17 @@ jobs: # 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.0 - - ruby-3.1 - - ruby-3.2 + - ruby-3.3 + - ruby-3.4 + - ruby-4.0 + fail-fast: false steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 with: ruby-version: ${{ matrix.ruby }} bundler: none diff --git a/.github/workflows/sync_default_gems.yml b/.github/workflows/sync_default_gems.yml new file mode 100644 index 0000000000..9fd1945449 --- /dev/null +++ b/.github/workflows/sync_default_gems.yml @@ -0,0 +1,80 @@ +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 + +permissions: + contents: read + +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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # zizmor: ignore[artipacked] + name: Check out ruby/ruby + with: + token: ${{ github.repository == 'ruby/ruby' && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.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/tarball-macos.yml b/.github/workflows/tarball-macos.yml new file mode 100644 index 0000000000..9bec94d528 --- /dev/null +++ b/.github/workflows/tarball-macos.yml @@ -0,0 +1,101 @@ +name: tarball-macos (reusable) + +on: + workflow_call: + inputs: + archname: + description: 'archname (e.g. snapshot-master, snapshot-ruby_3_3)' + required: true + type: string + notify-release-channel: + description: 'Also send failure notifications to SNAPSHOT_SLACK_WEBHOOK_URL (schedule/release builds).' + required: false + type: boolean + default: false + secrets: + SIMPLER_ALERTS_URL: + required: false + SNAPSHOT_SLACK_WEBHOOK_URL: + required: false + +permissions: + contents: read + +jobs: + macos: + strategy: + matrix: + test_task: [check, test-bundled-gems, test-bundler-parallel] + os: [macos-26, macos-15, macos-14] + include: + - os: macos-15-intel + test_task: check + fail-fast: false + runs-on: ${{ matrix.os }} + env: + ARCHNAME: ${{ inputs.archname }} + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: Packages + path: pkg + - name: Extract + run: tar xf pkg/*.tar.xz + - name: Install libraries + run: | + with_retry () { + "$@" || { sleep 5 && "$@"; } || { sleep 60 && "$@"; } + } + set -x + with_retry brew install gmp libffi openssl zlib autoconf automake libtool libyaml + - name: Set ENV + run: | + echo "JOBS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV + - name: configure + run: cd "$ARCHNAME/" && ./configure --with-openssl-dir=$(brew --prefix openssl) --with-libyaml-dir=$(brew --prefix libyaml) + - name: make + run: cd "$ARCHNAME/" && make $JOBS + - name: Tests + run: cd "$ARCHNAME/" && make $JOBS -s ${{ matrix.test_task }} + env: + RUBY_TESTOPTS: "-q --tty=no" + RUBY_DEBUG_TEST_NO_REMOTE: "1" + # leaked-globals since 2.7 + - name: Leaked Globals + run: cd "$ARCHNAME/" && make -s leaked-globals + if: matrix.test_task == 'check' + - name: make install without root privilege + run: cd "$ARCHNAME/" && make $JOBS install DESTDIR="/tmp/destdir" + if: matrix.test_task == 'check' + - name: make install + run: cd "$ARCHNAME/" && sudo make $JOBS install + if: matrix.test_task == 'check' + - name: Verify installed binaries + run: | + /usr/local/bin/ruby -v + /usr/local/bin/gem -v + /usr/local/bin/bundle -v + if: matrix.test_task == 'check' + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: .github/actions/slack + sparse-checkout-cone-mode: false + persist-credentials: false + if: ${{ failure() }} + - 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() }} + - uses: ruby/action-slack@d260b61aa817726d5bedd22dd6cc305787fa4cdd # v4.0.0 + with: + payload: | + { + "attachments": [{ + "text": "${{ job.status }}: ${{ matrix.os }} / ${{ matrix.test_task }} <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ inputs.archname }}>", + "color": "danger" + }] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SNAPSHOT_SLACK_WEBHOOK_URL }} + if: failure() && inputs.notify-release-channel diff --git a/.github/workflows/tarball-non-development.yml b/.github/workflows/tarball-non-development.yml new file mode 100644 index 0000000000..db6230b301 --- /dev/null +++ b/.github/workflows/tarball-non-development.yml @@ -0,0 +1,87 @@ +name: tarball-non-development (reusable) + +on: + workflow_call: {} + +permissions: + contents: read + +jobs: + non_development: + strategy: + fail-fast: false + matrix: + include: + - { variant: default, remove_ruby: false, configure_extra: '' } + - { variant: no-ruby, remove_ruby: true, configure_extra: '' } + - { variant: baseruby-no, remove_ruby: false, configure_extra: '--with-baseruby=no' } + runs-on: ubuntu-24.04 + env: + ruby_prefix: /tmp/ruby-snapshot + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: Packages + path: pkg + - name: Extract + run: tar xf pkg/*.tar.xz + - name: Substitute patchlevel + run: | + set -x + cd snapshot-*/ + sed -i.orig 's/^\( *# *define *RUBY_PATCHLEVEL\) *-.*/\1 0/' version.h + diff -u version.h.orig version.h || : + rm -f version.h.orig + - name: Install libraries + run: | + set -x + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev zlib1g-dev libffi-dev libgmp-dev bison- autoconf- + - name: Remove host ruby + if: matrix.remove_ruby + run: | + set -x + sudo apt-get purge -y -q 'ruby*' || : + sudo rm -rf /opt/hostedtoolcache/Ruby + ! command -v ruby + - name: Set ENV + run: | + echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - name: configure + run: cd snapshot-*/ && ./configure --prefix="${ruby_prefix}" ${{ matrix.configure_extra }} + - name: make + run: cd snapshot-*/ && make $JOBS + - name: Leaked Globals + run: cd snapshot-*/ && make -s leaked-globals + - name: make install + run: cd snapshot-*/ && make $JOBS install + - name: Set PATH + run: echo "PATH=${ruby_prefix}/bin:$PATH" >> $GITHUB_ENV + - name: Check patchlevel + id: check-patchlevel + run: | + exec "${ruby_prefix}/bin/ruby" -vx "$0" + #!ruby + puts "RUBY_PATCHLEVEL=#{RUBY_PATCHLEVEL.inspect}" + abort unless RUBY_PATCHLEVEL >= 0 + working-directory: ${{ env.ruby_prefix }} + continue-on-error: true + - name: Check LOADPATH + id: check-loadpath + run: | + exec ${ruby_prefix}/bin/ruby -vx "$0" + #!ruby + paths = $:.grep(/\+/) + pp paths + abort unless paths.empty? + working-directory: ${{ env.ruby_prefix }} + continue-on-error: true + - name: Check pathnames + id: check-pathnames + run: | + ! find -name '*+*' | grep + + working-directory: ${{ env.ruby_prefix }} + continue-on-error: true + - name: result + run: false + if: ${{ contains(steps.*.outcome, 'failure') }} diff --git a/.github/workflows/tarball-test-schedule.yml b/.github/workflows/tarball-test-schedule.yml new file mode 100644 index 0000000000..6684b09edb --- /dev/null +++ b/.github/workflows/tarball-test-schedule.yml @@ -0,0 +1,26 @@ +name: tarball-test-schedule +on: + schedule: + - cron: '30 18 * * *' # Daily at 18:30 UTC + workflow_dispatch: + +permissions: {} + +jobs: + dispatch: + if: ${{ github.event_name != 'schedule' || github.repository == 'ruby/ruby' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + branch: + - master + - ruby_4_0 + - ruby_3_4 + - ruby_3_3 + steps: + - name: Trigger tarball-test on ${{ matrix.branch }} + run: gh workflow run tarball-test.yml --ref "$BRANCH" --repo "$GITHUB_REPOSITORY" -f notify-release-channel=true + env: + BRANCH: ${{ matrix.branch }} + GH_TOKEN: ${{ secrets.MATZBOT_GITHUB_ACTION_TOKEN }} diff --git a/.github/workflows/tarball-test.yml b/.github/workflows/tarball-test.yml new file mode 100644 index 0000000000..52c4d31fc8 --- /dev/null +++ b/.github/workflows/tarball-test.yml @@ -0,0 +1,105 @@ +name: tarball-test +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: + workflow_dispatch: + inputs: + notify-release-channel: + description: 'Also send failure notifications to SNAPSHOT_SLACK_WEBHOOK_URL (set by tarball-test-schedule).' + type: boolean + default: false + +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: + tarball: + runs-on: ubuntu-latest + # Cherry-pick to maintenance branches by changing only env.BRANCH below; + # archname / branch-label / Materialize all derive from it. + env: + BRANCH: master + outputs: + branch: ${{ env.BRANCH }} + skip: ${{ steps.skipping.outputs.skip }} + steps: + - id: skipping + run: + echo 'skip=true' >> $GITHUB_OUTPUT + 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.pull_request.user.login == 'dependabot[bot]') + )}} + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 1 # actions/checkout fetches all heads/tags unless > 0 + persist-credentials: false + # tool/make-snapshot derives the branch name from HEAD and looks up + # the upstream during ChangeLog generation. Detached checkouts + # (pull_request, merge_group) lack a local branch with tracking, so + # pin one to HEAD and connect it to the matching origin ref. + - name: Materialize local branch + run: | + git fetch --no-tags --depth=1 origin "+refs/heads/$BASE:refs/remotes/origin/$BASE" + git checkout -B "$BRANCH" HEAD + git branch --set-upstream-to="origin/$BASE" "$BRANCH" + env: + BASE: ${{ github.base_ref || env.BRANCH }} + - uses: ./.github/actions/make-snapshot + with: + archname: snapshot-${{ env.BRANCH }} + srcdir: '.' + + ubuntu: + needs: tarball + if: ${{ ! needs.tarball.outputs.skip }} + uses: ./.github/workflows/tarball-ubuntu.yml + with: + archname: snapshot-${{ needs.tarball.outputs.branch }} + notify-release-channel: ${{ github.event_name == 'workflow_dispatch' && inputs.notify-release-channel || false }} + secrets: + SIMPLER_ALERTS_URL: ${{ secrets.SIMPLER_ALERTS_URL }} + SNAPSHOT_SLACK_WEBHOOK_URL: ${{ secrets.SNAPSHOT_SLACK_WEBHOOK_URL }} + + macos: + needs: tarball + if: ${{ ! needs.tarball.outputs.skip }} + uses: ./.github/workflows/tarball-macos.yml + with: + archname: snapshot-${{ needs.tarball.outputs.branch }} + notify-release-channel: ${{ github.event_name == 'workflow_dispatch' && inputs.notify-release-channel || false }} + secrets: + SIMPLER_ALERTS_URL: ${{ secrets.SIMPLER_ALERTS_URL }} + SNAPSHOT_SLACK_WEBHOOK_URL: ${{ secrets.SNAPSHOT_SLACK_WEBHOOK_URL }} + + windows: + needs: tarball + if: ${{ ! needs.tarball.outputs.skip }} + uses: ./.github/workflows/tarball-windows.yml + with: + archname: snapshot-${{ needs.tarball.outputs.branch }} + notify-release-channel: ${{ github.event_name == 'workflow_dispatch' && inputs.notify-release-channel || false }} + secrets: + SIMPLER_ALERTS_URL: ${{ secrets.SIMPLER_ALERTS_URL }} + SNAPSHOT_SLACK_WEBHOOK_URL: ${{ secrets.SNAPSHOT_SLACK_WEBHOOK_URL }} + + non_development: + needs: tarball + uses: ./.github/workflows/tarball-non-development.yml diff --git a/.github/workflows/tarball-ubuntu.yml b/.github/workflows/tarball-ubuntu.yml new file mode 100644 index 0000000000..03f2f946b5 --- /dev/null +++ b/.github/workflows/tarball-ubuntu.yml @@ -0,0 +1,150 @@ +name: tarball-ubuntu (reusable) + +on: + workflow_call: + inputs: + archname: + description: 'archname (e.g. snapshot-master, snapshot-ruby_3_3)' + required: true + type: string + notify-release-channel: + description: 'Also send failure notifications to SNAPSHOT_SLACK_WEBHOOK_URL (schedule/release builds).' + required: false + type: boolean + default: false + secrets: + SIMPLER_ALERTS_URL: + required: false + SNAPSHOT_SLACK_WEBHOOK_URL: + required: false + +permissions: + contents: read + +jobs: + ubuntu: + strategy: + matrix: + test_task: [check, test-bundler-parallel, test-bundled-gems] + os: [ubuntu-24.04, ubuntu-22.04] + fail-fast: false + runs-on: ${{ matrix.os }} + env: + ARCHNAME: ${{ inputs.archname }} + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: Packages + path: pkg + - name: Extract + run: tar xf pkg/*.tar.xz + - name: Install libraries + run: | + set -x + sudo apt-get update -q + sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev zlib1g-dev libffi-dev libgmp-dev bison- autoconf- + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + ruby-version: '3.2' + # test-bundled-gems requires executable host ruby + if: matrix.test_task == 'test-bundled-gems' + - name: Fixed world writable dirs + run: | + mkdir -p $HOME/.local/share + mkdir -p $HOME/.cache/gem/specs + mkdir -p $HOME/.bundle/cache + mkdir -p $HOME/.ssh + chmod a-w $HOME/.bundle + # chmod a-w $HOME + # allow to write $HOME and check stats of HOME around tests (see below) + chmod -v a-w $HOME/.config + sudo chmod -R a-w /usr/share + sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v a-w $d; done' || : + - name: Set ENV + run: | + echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + - name: configure + run: cd "$ARCHNAME/" && ./configure + - name: make + run: cd "$ARCHNAME/" && make $JOBS + - name: Save stats of HOME + run: | + set -euxo pipefail + cat >"$ARCHNAME/save-stats.rb" <<'EOF' + require 'pathname' + require 'digest' + out = [] + [ + Dir.home, + ].each do |dir| + Dir.each_child(dir) do |pn| + st = File.stat(pn) + if st.file? + content = Digest::SHA1.file(pn).hexdigest + elsif st.directory? && st.nlink <= 10 + content = Dir.children(pn).sort + end + out << [pn, "%o"%st.mode, st.nlink, st.uid, st.gid, st.size, content].to_s + rescue + out << [pn, $!.inspect].to_s + end + end + File.open(ARGV.shift, "w") do |io| + io.puts out.sort + end + EOF + make -C "$ARCHNAME" TESTRUN_SCRIPT=save-stats.rb RUNOPT=/tmp/stat-before-tests.txt runruby + - name: Tests + run: cd "$ARCHNAME/" && make $JOBS -s ${{ matrix.test_task }} + env: + RUBY_TESTOPTS: "-q --tty=no" + # test_sync_default_gems triggers gpg, whose agent processes leave + # $HOME/.gnupg around even when GNUPGHOME points elsewhere. + - name: Forcibly remove ~/.gnupg + run: rm -rf $HOME/.gnupg + - name: Diff stats of HOME + run: | + make -C "$ARCHNAME" TESTRUN_SCRIPT=save-stats.rb RUNOPT=/tmp/stat-after-tests.txt runruby + rm -f "$ARCHNAME/save-stats.rb" + diff -u /tmp/stat-before-tests.txt /tmp/stat-after-tests.txt + # leaked-globals since 2.7 + - name: Leaked Globals + run: cd "$ARCHNAME/" && make -s leaked-globals + if: matrix.test_task == 'check' + - name: make install without root privilege + run: cd "$ARCHNAME/" && make $JOBS install DESTDIR="/tmp/destdir" + if: matrix.test_task == 'check' + - name: make install + run: cd "$ARCHNAME/" && sudo make $JOBS install + if: matrix.test_task == 'check' + - name: Verify installed binaries + run: | + /usr/local/bin/ruby -v + /usr/local/bin/gem -v + /usr/local/bin/bundle -v + if: matrix.test_task == 'check' + - name: Show .local + run: find $HOME/.local -ls + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: .github/actions/slack + sparse-checkout-cone-mode: false + persist-credentials: false + if: ${{ failure() }} + - 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() }} + - uses: ruby/action-slack@d260b61aa817726d5bedd22dd6cc305787fa4cdd # v4.0.0 + with: + payload: | + { + "attachments": [{ + "text": "${{ job.status }}: ${{ matrix.os }} / ${{ matrix.test_task }} <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ inputs.archname }}>", + "color": "danger" + }] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SNAPSHOT_SLACK_WEBHOOK_URL }} + if: failure() && inputs.notify-release-channel diff --git a/.github/workflows/tarball-windows.yml b/.github/workflows/tarball-windows.yml new file mode 100644 index 0000000000..1ce95de6fc --- /dev/null +++ b/.github/workflows/tarball-windows.yml @@ -0,0 +1,163 @@ +name: tarball-windows (reusable) + +on: + workflow_call: + inputs: + archname: + description: 'archname (e.g. snapshot-master)' + required: true + type: string + notify-release-channel: + description: 'Also send failure notifications to SNAPSHOT_SLACK_WEBHOOK_URL (schedule/release builds).' + required: false + type: boolean + default: false + secrets: + SIMPLER_ALERTS_URL: + required: false + SNAPSHOT_SLACK_WEBHOOK_URL: + required: false + +permissions: + contents: read + +jobs: + windows: + strategy: + matrix: + include: + - os: '2022' + test_task: check + - os: '2025-vs2026' + test_task: check + fail-fast: false + runs-on: windows-${{ matrix.os }} + defaults: + run: + shell: cmd + working-directory: build + name: Windows ${{ matrix.os }} (${{ matrix.test_task }}) + env: + GITPULLOPTIONS: --no-tags origin ${{github.ref}} + PATCH: C:\msys64\usr\bin\patch.exe + OS_VER: windows-${{ matrix.os }} + # see https://github.com/ruby/ruby/commit/9ff4399decef0036897d3cfb9ac2c710dea913ca + OPENSSL_MODULES: C:\vcpkg\installed\x64-windows\bin + steps: + - run: md build + working-directory: + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + ruby-version: '3.2' + bundler: none + windows-toolchain: none + + - uses: msys2/setup-msys2@e9898307ac31d1a803454791be09ab9973336e1c # v2.31.1 + id: setup-msys2 + with: + update: true + install: >- + patch + - name: patch path + shell: msys2 {0} + run: echo PATCH=$(cygpath -wa $(command -v patch)) >> $GITHUB_ENV + if: ${{ steps.setup-msys2.outcome == 'success' }} + - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: C:\vcpkg\installed + key: ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}- + ${{ runner.os }}-vcpkg-installed- + - name: Install libraries with vcpkg + run: | + vcpkg --triplet x64-windows install gmp libffi libyaml openssl zlib + + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: Packages + path: pkg + - name: Extract + run: 7z x pkg/*.zip + working-directory: + + - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: snapshot-*/.downloaded-cache + key: downloaded-cache + + - name: setup env + # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent. + # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302 + env: + ARCHNAME: ${{ inputs.archname }} + run: | + set > old.env + call ..\%ARCHNAME%\win32\vssetup.cmd + set TMP=%USERPROFILE%\AppData\Local\Temp + set TEMP=%USERPROFILE%\AppData\Local\Temp + set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul + set > new.env + + - name: update env + shell: pwsh + run: | + $old = (Get-Content old.env); $new = (Get-Content new.env) + del *.env + Compare-Object $old $new | + Where-Object { $_.SideIndicator -eq '=>' } | + Select-Object -ExpandProperty InputObject | + Add-Content -Path $env:GITHUB_ENV + - name: link libraries + run: | + for %%I in (C:\vcpkg\installed\x64-windows\bin\*.dll) do ( + mklink %%~nxI %%I + ) + - name: Configure + env: + ARCHNAME: ${{ inputs.archname }} + run: >- + ../%ARCHNAME%/win32/configure.bat --disable-install-doc + --with-opt-dir=C:/vcpkg/installed/x64-windows + - run: nmake incs + - run: nmake extract-extlibs + - run: nmake + env: + YACC: win_bison + + - name: ruby -v + run: .\ruby -v + + - run: nmake test + timeout-minutes: 5 + + - run: nmake ${{ matrix.test_task }} + env: + RUBY_TESTOPTS: -j${{env.TEST_JOBS}} + timeout-minutes: 70 + continue-on-error: ${{ matrix.continue-on-error || false }} + + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: .github/actions/slack + sparse-checkout-cone-mode: false + persist-credentials: false + if: ${{ failure() }} + - uses: ./.github/actions/slack + with: + label: "${{ env.OS_VER }} / ${{ matrix.test_task }}" + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + - uses: ruby/action-slack@d260b61aa817726d5bedd22dd6cc305787fa4cdd # v4.0.0 + with: + payload: | + { + "attachments": [{ + "text": "${{ job.status }}: ${{ env.OS_VER }} / ${{ matrix.test_task }} <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ inputs.archname }}>", + "color": "danger" + }] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SNAPSHOT_SLACK_WEBHOOK_URL }} + if: failure() && inputs.notify-release-channel diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 93ced0d1d2..09e96f764c 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,13 +12,6 @@ on: # 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: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -31,58 +24,76 @@ jobs: make: strategy: matrix: - test_task: [check] - arch: [''] - configure: ['cppflags=-DVM_CHECK_MODE'] - # specifying other jobs with `include` to avoid redundant tests + # 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: + env: &make-env GITPULLOPTIONS: --no-tags origin ${{ github.ref }} RUBY_DEBUG: ci - runs-on: ubuntu-20.04 + 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + steps: &make-steps + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + persist-credentials: false - uses: ./.github/actions/setup/ubuntu with: arch: ${{ matrix.arch }} + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.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} + $SETARCH ../src/configure -C --disable-install-doc ${configure:- --enable-debug-env cppflags=-DRUBY_DEBUG} ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} - run: $SETARCH make prepare-gems @@ -90,31 +101,162 @@ jobs: - 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: >- - $SETARCH make -s ${{ matrix.test_task }} - ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`} + 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: 40 + timeout-minutes: ${{ matrix.timeout || 40 }} env: RUBY_TESTOPTS: '-q --tty=no' - TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} 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=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'` + $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}" env: GNUMAKEFLAGS: '' RUBY_TESTOPTS: '-v --tty=no' - TESTS: ${{ matrix.skipped_tests }} - if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }} + 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.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=shipit' + + 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.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: ruby/ruby-bench + persist-credentials: false + 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 + env: + BUNDLER_VERSION: 0 + - uses: ./.github/actions/slack with: - label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }} + 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() }} @@ -125,6 +267,7 @@ jobs: needs: [make] steps: - run: exit 1 + working-directory: if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index f69df0f58d..edb2c76c48 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -11,19 +11,12 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -50,26 +43,32 @@ jobs: env: RUBY_TESTOPTS: '-q --tty=no' GITPULLOPTIONS: --no-tags origin ${{ github.ref }} - WASI_SDK_VERSION_MAJOR: 20 + WASI_SDK_VERSION_MAJOR: 25 WASI_SDK_VERSION_MINOR: 0 BINARYEN_VERSION: 113 WASMTIME_VERSION: v15.0.0 - runs-on: ubuntu-20.04 + 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + persist-credentials: false + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + ruby-version: '3.1' + bundler: none - uses: ./.github/actions/setup/directories with: @@ -83,7 +82,7 @@ jobs: 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}_amd64.deb" + 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" @@ -105,29 +104,50 @@ jobs: run: | echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV - - name: Build baseruby + - uses: ./.github/actions/setup/baseruby + id: baseruby + with: + srcdir: src + + - name: Download config.guess with wasi version run: | - set -ex - mkdir ../baseruby - pushd ../baseruby - ../src/configure --prefix=$PWD/install - make - make install + 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=bigdecimal,cgi/escape,continuation,coverage,date,dbm,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,fiber,gdbm,json,json/generator,json/parser,nkf,objspace,pathname,racc/cparse,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 }}" + run: >- + ../src/configure + --host wasm32-unknown-wasi + --with-baseruby="${{ steps.baseruby.outputs.ruby }}" + --with-dump-ast="${{ steps.baseruby.outputs.dump_ast }}" + --with-static-linked-ext + --with-ext=${EXTS// /,} + 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 }}" + env: + EXTS: + cgi/escape + continuation + coverage + date + digest + digest/* + erb/escape + etc + fcntl + json + json/* + objspace + rbconfig/sizeof + ripper + stringio + strscan # miniruby may not be built when cross-compling - run: make mini ruby @@ -136,10 +156,13 @@ jobs: - run: tar cfz ../install.tar.gz -C ../install . - name: Upload artifacts - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 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 @@ -157,6 +180,16 @@ jobs: 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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + 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 index 8b34f962fe..13551427bb 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -3,27 +3,15 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' - '.*.yml' pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' + # 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: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -37,164 +25,184 @@ jobs: strategy: matrix: include: - - vs: 2019 - - vs: 2022 + - os: 2022 + test_task: check + - os: 2022 + test_task: test-bundled-gems + - os: 2025-vs2026 + test_task: check + - os: 2025-vs2026 + test_task: test-bundled-gems + - os: 11-arm + test_task: 'btest test-basic test-tool' # check and test-spec are broken yet. + target: arm64 fail-fast: false - runs-on: windows-${{ matrix.vs < 2022 && '2019' || matrix.vs }} + 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/vcpkg')) )}} - name: VisualStudio ${{ matrix.vs }} + name: Windows ${{ matrix.os }} (${{ matrix.test_task }}) env: GITPULLOPTIONS: --no-tags origin ${{ github.ref }} - OS_VER: windows-${{ matrix.vs < 2022 && '2019' || matrix.vs }} - # FIXME: This is a workaround for the vcpkg's issue present as of openssl 3.1.1 - # where OpenSSL's default modules directory is incorrectly set to C:\vcpkg\packages\openssl_x64-windows\bin - # cf. https://github.com/ruby/openssl/pull/635#issuecomment-1596833720 - OPENSSL_MODULES: C:\vcpkg\installed\x64-windows\bin + VCPKG_DEFAULT_TRIPLET: ${{ matrix.target || 'x64' }}-windows steps: - run: md build working-directory: - - name: find tools - id: find-tools - run: | - ::- find needed tools - set NEEDS= - for %%I in (%NEEDED_TOOLS%) do if "%%~$PATH:I" == "" ( - call set NEEDS=%%NEEDS%% %%~nI - ) else ( - echo %%I: %%~$PATH:I - ) - echo.needs=%NEEDS%>>%GITHUB_OUTPUT% - if "%NEEDS%" == "" ( - echo [debug] All needed tools found - ) else ( - echo [warning^]Needs%NEEDS% - ) - env: - NEEDED_TOOLS: >- - patch.exe - - - uses: msys2/setup-msys2@d40200dc2db4c351366b048a9565ad82919e1c24 # v2 - id: setup-msys2 + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 with: - update: true - install: >- - ${{ steps.find-tools.outputs.needs }} - if: ${{ steps.find-tools.outputs.needs != '' }} + # 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/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - path: C:\vcpkg\downloads - key: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}- - ${{ runner.os }}-vcpkg-download- + persist-credentials: false + sparse-checkout-cone-mode: false + sparse-checkout: /.github - - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + - uses: ./.github/actions/setup/directories with: - path: C:\vcpkg\installed - key: ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}- - ${{ runner.os }}-vcpkg-installed- - - - name: Install libraries with vcpkg - run: | - vcpkg --triplet x64-windows install libffi libyaml openssl readline zlib + srcdir: src + builddir: build + make-command: nmake + clean: true - - name: Install libraries with scoop + - name: Install tools with scoop run: | - iex "& {$(irm get.scoop.sh)} -RunAsAdmin" + if ((vcpkg.exe help install) -match "manifest") { exit } + 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 shell: pwsh - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Restore vcpkg artifact + id: restore-vcpkg + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - sparse-checkout-cone-mode: false - sparse-checkout: /.github + path: src\vcpkg_installed + key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }} - - uses: ./.github/actions/setup/directories + - name: Install libraries with vcpkg + run: | + vcpkg install + working-directory: src + if: ${{ ! steps.restore-vcpkg.outputs.cache-hit }} + + - name: Save vcpkg artifact + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - srcdir: src - builddir: build + 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 VS=${{ matrix.vs }} - set VCVARS=${{ matrix.vcvars || '' }} - if not "%VCVARS%" == "" goto :vcset - set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - :vcset - set | C:\msys64\usr\bin\sort > old.env - call %VCVARS% + set > old.env + call ..\src\win32\vssetup.cmd ^ + -arch=${{ matrix.target || 'amd64' }} ^ + ${{ matrix.vcvars && '-vcvars_ver=' || '' }}${{ matrix.vcvars }} nmake -f nul - set TMP=%USERPROFILE%\AppData\Local\Temp - set TEMP=%USERPROFILE%\AppData\Local\Temp + set TMP=%RUNNER_TEMP% + set TEMP=%RUNNER_TEMP% set MAKEFLAGS=l set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul - set | C:\msys64\usr\bin\sort > new.env - C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV% + set RUBY_OPT_DIR=%GITHUB_WORKSPACE:\=/%/src/vcpkg_installed/%VCPKG_DEFAULT_TRIPLET% + set > new.env + + - name: update env + shell: pwsh + run: | + $old = (Get-Content old.env); $new = (Get-Content new.env) del *.env + Compare-Object $old $new | + Where-Object { $_.SideIndicator -eq '=>' } | + Select-Object -ExpandProperty InputObject | + Add-Content -Path $env:GITHUB_ENV + + - name: baseruby version + run: ruby -v - name: compiler version run: cl - - name: link libraries - run: | - for %%I in (C:\vcpkg\installed\x64-windows\bin\*.dll) do ( - if not %%~nI == readline mklink %%~nxI %%I - ) - # We use OpenSSL instealled by vcpkg instead - - name: disable system OpenSSL - run: | - for %%I in (libcrypto-1_1-x64 libssl-1_1-x64) do ( - ren c:\Windows\System32\%%I.dll %%I.dll_ - ) - # windows-2019 image doesn't have OpenSSL as of 2023/9/14 - if: ${{ matrix.vs != 2019 }} + - 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=C:/vcpkg/installed/x64-windows + --with-opt-dir=%RUBY_OPT_DIR% + --with-gmp + + - run: nmake prepare-vcpkg - run: nmake incs - run: nmake extract-extlibs - - run: nmake + # 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 - - run: nmake test - timeout-minutes: 5 + # 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 - - run: nmake test-spec - timeout-minutes: 10 + - 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 test-all + - run: nmake ${{ matrix.test_task || 'check' }} env: - RUBY_TESTOPTS: -j${{ env.TEST_JOBS || 4 }} --job-status=normal - timeout-minutes: 60 + RUBY_TESTOPTS: -j${{ env.TEST_JOBS || 4 }} + timeout-minutes: 70 - uses: ./.github/actions/slack with: - label: VS${{ matrix.vs }} / ${{ matrix.test_task || 'check' }} + label: Windows ${{ matrix.os }} / ${{ 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-2025-vs2026 + 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/wsl.yml b/.github/workflows/wsl.yml new file mode 100644 index 0000000000..470b68fe66 --- /dev/null +++ b/.github/workflows/wsl.yml @@ -0,0 +1,73 @@ +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: + +permissions: + contents: read + +jobs: + wsl: + runs-on: windows-2025-vs2026 + + 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.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 index 11e200a619..b52c6355ad 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -1,24 +1,23 @@ -name: YJIT macOS Arm64 +name: YJIT macOS on: push: + branches: + - master paths-ignore: - 'doc/**' - - '**/man' + - '**/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: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -31,19 +30,20 @@ jobs: cargo: name: cargo test - runs-on: macos-arm-oss + runs-on: macos-26 if: >- - ${{github.repository == 'ruby/ruby' && - !(false + ${{!(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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) )}} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - run: RUST_BACKTRACE=1 cargo test working-directory: yjit @@ -66,28 +66,30 @@ jobs: - 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-arm-oss + runs-on: macos-26 if: >- - ${{github.repository == 'ruby/ruby' && - !(false + ${{!(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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) )}} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + persist-credentials: false - name: Install libraries uses: ./.github/actions/setup/macos @@ -98,6 +100,8 @@ jobs: 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 }} @@ -107,30 +111,74 @@ jobs: - run: make - - name: Enable YJIT through ENV - run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV + - 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-26 + 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: | - make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`} + 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' - TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} 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=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'` + make -s test-all TESTS="${TESTS//-n!\//-n/}" env: GNUMAKEFLAGS: '' RUBY_TESTOPTS: '-v --tty=no' - TESTS: ${{ matrix.skipped_tests }} PRECHECK_BUNDLED_GEMS: 'no' - if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }} + 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 }} @@ -138,12 +186,14 @@ jobs: if: ${{ failure() }} result: - if: ${{ always() && github.repository == 'ruby/ruby' }} + if: ${{ always() }} name: ${{ github.workflow }} result - runs-on: macos-arm-oss + runs-on: ubuntu-latest needs: [make] steps: - - run: exit 1 + - name: ${{ github.workflow }} jobs have failed + run: exit 1 + working-directory: if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index ec8483b7d1..934c3f56d4 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,13 +12,6 @@ on: # 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: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -32,18 +25,20 @@ jobs: name: cargo test # GitHub Action's image seems to already contain a Rust 1.58.0. - runs-on: ubuntu-20.04 + 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) )}} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false # For now we can't run cargo test --offline because it complains about the # capstone dependency, even though the dependency is optional @@ -64,18 +59,20 @@ jobs: name: cargo clippy # GitHub Action's image seems to already contain a Rust 1.58.0. - runs-on: ubuntu-20.04 + 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) )}} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false # Check that we don't have linting errors in release mode, too - run: cargo clippy --all-targets --all-features @@ -88,7 +85,9 @@ jobs: include: - test_task: 'yjit-bindgen' hint: 'To fix: use patch in logs' - configure: '--with-gcc=clang-12 --enable-yjit=dev' + # 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 @@ -102,51 +101,62 @@ jobs: - 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' - - test_task: 'yjit-bench' - configure: '--enable-yjit=dev' - yjit_bench_opts: '--yjit-stats' - 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 - BUNDLE_JOBS: 8 # for yjit-bench RUST_BACKTRACE: 1 - runs-on: ubuntu-20.04 + 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.actor == 'dependabot[bot]') + || (github.event.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) )}} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + persist-credentials: false - uses: ./.github/actions/setup/ubuntu + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.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 }} @@ -157,30 +167,62 @@ jobs: - run: make - - name: Enable YJIT through ENV - run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV + - 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: make -s -j ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS" - timeout-minutes: 60 + 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: 'rbs' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' PRECHECK_BUNDLED_GEMS: 'no' SYNTAX_SUGGEST_TIMEOUT: '5' YJIT_BINDGEN_DIFF_OPTS: '--exit-code' - continue-on-error: ${{ matrix.test_task == 'yjit-bench' }} + 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: Show ${{ github.event.pull_request.base.ref }} GitHub URL for yjit-bench comparison - run: echo "https://github.com/${BASE_REPO}/commit/${BASE_SHA}" - env: - BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }} - BASE_SHA: ${{ github.event.pull_request.base.sha }} - if: ${{ matrix.test_task == 'yjit-bench' && startsWith(github.event_name, 'pull') }} + - 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: @@ -195,6 +237,7 @@ jobs: needs: [make] steps: - run: exit 1 + working-directory: if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml new file mode 100644 index 0000000000..f9282d64e8 --- /dev/null +++ b/.github/workflows/zjit-macos.yml @@ -0,0 +1,239 @@ +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 }} + RUST_BACKTRACE: 1 + ZJIT_RB_BUG: 1 + + runs-on: macos-26 + + 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.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + persist-credentials: false + + - 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@13608cbb45b01feb47ef444ab1a42dc41ad56f1a # v2.79.11 + 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: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: macos-26 + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + is-zjit: 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" \ + TESTOPTS="$TESTOPTS" + timeout-minutes: 60 + env: + RUBY_TESTOPTS: '-q --tty=no' + EXCLUDES: '../src/test/.excludes-zjit' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + SYNTAX_SUGGEST_TIMEOUT: '30' + 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: 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') }} + + # 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=shipit' + configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow + + runs-on: macos-26 + + 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.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + 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 + env: + BUNDLER_VERSION: 0 + + - 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..1e7bec3859 --- /dev/null +++ b/.github/workflows/zjit-ubuntu.yml @@ -0,0 +1,293 @@ +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.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - 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.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + persist-credentials: false + + - uses: ./.github/actions/setup/ubuntu + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + ruby-version: '3.1' + bundler: none + + - uses: taiki-e/install-action@13608cbb45b01feb47ef444ab1a42dc41ad56f1a # v2.79.11 + 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: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: ${{ matrix.runs-on || 'ubuntu-22.04' }} + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + is-zjit: 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" \ + 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: '30' + ZJIT_BINDGEN_DIFF_OPTS: '--exit-code' + CLANG_PATH: ${{ matrix.clang_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-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=shipit' + 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.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/cargo')) + )}} + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: ruby/ruby-bench + persist-credentials: false + 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 + env: + BUNDLER_VERSION: 0 + + - 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 |
