# frozen_string_literal: true ## # Base class for the RDoc code tree. # # We contain the common stuff for contexts (which are containers) and other # elements (methods, attributes and so on) # # Here's the tree of the CodeObject subclasses: # # * RDoc::Context # * RDoc::TopLevel # * RDoc::ClassModule # * RDoc::AnonClass (never used so far) # * RDoc::NormalClass # * RDoc::NormalModule # * RDoc::SingleClass # * RDoc::MethodAttr # * RDoc::Attr # * RDoc::AnyMethod # * RDoc::GhostMethod # * RDoc::MetaMethod # * RDoc::Alias # * RDoc::Constant # * RDoc::Mixin # * RDoc::Require # * RDoc::Include class RDoc::CodeObject include RDoc::Text ## # Our comment attr_reader :comment ## # Do we document our children? attr_reader :document_children ## # Do we document ourselves? attr_reader :document_self ## # Are we done documenting (ie, did we come across a :enddoc:)? attr_reader :done_documenting ## # Which file this code object was defined in attr_reader :file ## # Force documentation of this CodeObject attr_reader :force_documentation ## # Line in #file where this CodeObject was defined attr_accessor :line ## # Hash of arbitrary metadata for this CodeObject attr_reader :metadata ## # Sets the parent CodeObject attr_writer :parent ## # Did we ever receive a +:nodoc:+ directive? attr_reader :received_nodoc ## # Set the section this CodeObject is in attr_writer :section ## # The RDoc::Store for this object. attr_reader :store ## # We are the model of the code, but we know that at some point we will be # worked on by viewers. By implementing the Viewable protocol, viewers can # associated themselves with these objects. attr_accessor :viewer ## # Creates a new CodeObject that will document itself and its children def initialize @metadata = {} @comment = '' @parent = nil @parent_name = nil # for loading @parent_class = nil # for loading @section = nil @section_title = nil # for loading @file = nil @full_name = nil @store = nil @track_visibility = true initialize_visibility end ## # Initializes state for visibility of this CodeObject and its children. def initialize_visibility # :nodoc: @document_children = true @document_self = true @done_documenting = false @force_documentation = false @received_nodoc = false @ignored = false @suppressed = false @track_visibility = true end ## # Replaces our comment with +comment+, unless it is empty. def comment=(comment) @comment = case comment when NilClass then '' when RDoc::Markup::Document then comment when RDoc::Comment then comment.normalize else if comment and not comment.empty? then normalize_comment comment else # HACK correct fix is to have #initialize create @comment # with the correct encoding if String === @comment and @comment.empty? then @comment = RDoc::Encoding.change_encoding @comment, comment.encoding end @comment end end end ## # Should this CodeObject be displayed in output? # # A code object should be displayed if: # # * The item didn't have a nodoc or wasn't in a container that had nodoc # * The item wasn't ignored # * The item has documentation and was not suppressed def display? @document_self and not @ignored and (documented? or not @suppressed) end ## # Enables or disables documentation of this CodeObject's children unless it # has been turned off by :enddoc: def document_children=(document_children) return unless @track_visibility @document_children = document_children unless @done_documenting end ## # Enables or disables documentation of this CodeObject unless it has been # turned off by :enddoc:. If the argument is +nil+ it means the # documentation is turned off by +:nodoc:+. def document_self=(document_self) return unless @track_visibility return if @done_documenting @document_self = document_self @received_nodoc = true if document_self.nil? end ## # Does this object have a comment with content or is #received_nodoc true? def documented? @received_nodoc or !@comment.empty? end ## # Turns documentation on/off, and turns on/off #document_self # and #document_children. # # Once documentation has been turned off (by +:enddoc:+), # the object will refuse to turn #document_self or # #document_children on, so +:doc:+ and +:start_doc:+ directives # will have no effect in the current file. def done_documenting=(value) return unless @track_visibility @done_documenting = value @document_self = !value @document_children = @document_self end ## # Yields each parent of this CodeObject. See also # RDoc::ClassModule#each_ancestor def each_parent code_object = self while code_object = code_object.parent do yield code_object end self end ## # File name where this CodeObject was found. # # See also RDoc::Context#in_files def file_name return unless @file @file.absolute_name end ## # Force the documentation of this object unless documentation # has been turned off by :enddoc: #-- # HACK untested, was assigning to an ivar def force_documentation=(value) @force_documentation = value unless @done_documenting end ## # Sets the full_name overriding any computed full name. # # Set to +nil+ to clear RDoc's cached value def full_name= full_name @full_name = full_name end ## # Use this to ignore a CodeObject and all its children until found again # (#record_location is called). An ignored item will not be displayed in # documentation. # # See github issue #55 # # The ignored status is temporary in order to allow implementation details # to be hidden. At the end of processing a file RDoc allows all classes # and modules to add new documentation to previously created classes. # # If a class was ignored (via stopdoc) then reopened later with additional # documentation it should be displayed. If a class was ignored and never # reopened it should not be displayed. The ignore flag allows this to # occur. def ignore return unless @track_visibility @ignored = true stop_doc end ## # Has this class been ignored? # # See also #ignore def ignored? @ignored end ## # The options instance from the store this CodeObject is attached to, or a # default options instance if the CodeObject is not attached. # # This is used by Text#snippet def options if @store and @store.rdoc then @store.rdoc.options else RDoc::Options.new end end ## # Our parent CodeObject. The parent may be missing for classes loaded from # legacy RI data stores. def parent return @parent if @parent return nil unless @parent_name if @parent_class == RDoc::TopLevel then @parent = @store.add_file @parent_name else @parent = @store.find_class_or_module @parent_name return @parent if @parent begin @parent = @store.load_class @parent_name rescue RDoc::Store::MissingFileError nil end end end ## # File name of our parent def parent_file_name @parent ? @parent.base_name : '(unknown)' end ## # Name of our parent def parent_name @parent ? @parent.full_name : '(unknown)' end ## # Records the RDoc::TopLevel (file) where this code object was defined def record_location top_level @ignored = false @suppressed = false @file = top_level end ## # The section this CodeObject is in. Sections allow grouping of constants, # attributes and methods inside a class or module. def section return @section if @section @section = parent.add_section @section_title if parent end ## # Enable capture of documentation unless documentation has been # turned off by :enddoc: def start_doc return if @done_documenting @document_self = true @document_children = true @ignored = false @suppressed = false end ## # Disable capture of documentation def stop_doc return unless @track_visibility @document_self = false @document_children = false end ## # Sets the +store+ that contains this CodeObject def store= store @store = store return unless @track_visibility if :nodoc == options.visibility then initialize_visibility @track_visibility = false end end ## # Use this to suppress a CodeObject and all its children until the next file # it is seen in or documentation is discovered. A suppressed item with # documentation will be displayed while an ignored item with documentation # may not be displayed. def suppress return unless @track_visibility @suppressed = true stop_doc end ## # Has this class been suppressed? # # See also #suppress def suppressed? @suppressed end end 33c567fd78aa43f2ee'>.github/actions/setup/ubuntu/action.yml
diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 9bc135873c..0000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,98 +0,0 @@ ---- -version: '{build}' -init: - - git config --global user.name git - - git config --global user.email svn-admin@ruby-lang.org - - git config --global core.autocrlf false - - git config --global core.eol lf - - git config --global advice.detachedHead 0 -shallow_clone: true -clone_depth: 10 -platform: - - x64 -environment: - ruby_version: "24-%Platform%" - zlib_version: "1.2.11" - matrix: - - build: vs - vs: 120 - ssl: OpenSSL - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - GEMS_FOR_TEST: "" - - build: vs - vs: 140 - ssl: OpenSSL-v111 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - GEMS_FOR_TEST: "" - RELINE_TEST_ENCODING: "Windows-31J" -for: -- - matrix: - only: - - build: vs - install: - - ver - - chcp - - SET BITS=%Platform:x86=32% - - SET BITS=%BITS:x=% - - SET OPENSSL_DIR=C:\%ssl%-Win%BITS% - - CALL SET vcvars=%%^VS%VS%COMNTOOLS^%%..\..\VC\vcvarsall.bat - - SET vcvars - - '"%vcvars%" %Platform:x64=amd64%' - - SET ruby_path=C:\Ruby%ruby_version:-x86=% - - SET PATH=\usr\local\bin;%ruby_path%\bin;%PATH%;C:\msys64\mingw64\bin;C:\msys64\usr\bin - - ruby --version - - 'cl' - - echo> Makefile srcdir=. - - echo>> Makefile MSC_VER=0 - - echo>> Makefile RT=none - - echo>> Makefile RT_VER=0 - - echo>> Makefile BUILTIN_ENCOBJS=nul - - type win32\Makefile.sub >> Makefile - - nmake %mflags% up VCSUP="echo Update OK" - - nmake %mflags% extract-extlibs - - del Makefile - - mkdir \usr\local\bin - - mkdir \usr\local\include - - mkdir \usr\local\lib - - SET ZLIB_ZIP=.downloaded-cache\zlib%zlib_version:.=%.zip - - if not exist %ZLIB_ZIP% curl -fsSL -o %ZLIB_ZIP% --retry 10 https://zlib.net/zlib%zlib_version:.=%.zip - - 7z x -aos -o%APPVEYOR_BUILD_FOLDER%\ext\zlib %ZLIB_ZIP% - - for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I - - attrib +r /s /d - - mkdir %Platform%-mswin_%vs% - build_script: - - cd %APPVEYOR_BUILD_FOLDER% - - cd %Platform%-mswin_%vs% - - ..\win32\configure.bat --without-ext=+,dbm,gdbm,readline --with-opt-dir=/usr/local --with-openssl-dir=%OPENSSL_DIR:\=/% - - nmake -l - - nmake install-nodoc - - \usr\bin\ruby -v -e "p :locale => Encoding.find('locale'), :filesystem => Encoding.find('filesystem')" - - if not "%GEMS_FOR_TEST%" == "" \usr\bin\gem install --no-document %GEMS_FOR_TEST% - - \usr\bin\ruby -ropenssl -e "puts 'Build ' + OpenSSL::OPENSSL_VERSION, 'Runtime ' + OpenSSL::OPENSSL_LIBRARY_VERSION" - test_script: - - set /a JOBS=%NUMBER_OF_PROCESSORS% - - nmake -l "TESTOPTS=-v -q" btest - - nmake -l "TESTOPTS=-v -q" test-basic - - nmake -l "TESTOPTS=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor -j%JOBS% --exclude readline --exclude win32ole --exclude test_bignum --exclude test_syntax --exclude test_open-uri --exclude test_bundled_ca" test-all - # separately execute tests without -j which may crash worker with -j. - - nmake -l "TESTOPTS=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor" test-all TESTS="../test/win32ole ../test/ruby/test_bignum.rb ../test/ruby/test_syntax.rb ../test/open-uri/test_open-uri.rb ../test/rubygems/test_bundled_ca.rb" - - nmake -l test-spec MSPECOPT=-fs # not using `-j` because sometimes `mspec -j` silently dies on Windows -notifications: - - provider: Webhook - method: POST - url: - secure: CcFlJNDJ/a6to7u3Z4Fnz6dScEPNx7hTha2GkSRlV+1U6dqmxY/7uBcLXYb9gR3jfQk6w+2o/HrjNAyXMNGU/JOka3s2WRI4VKitzM+lQ08owvJIh0R7LxrGH0J2e81U # ruby-lang slack: ruby/simpler-alerts-bot - body: >- - {{^isPullRequest}} - { - "ci": "AppVeyor CI", - "env": "Visual Studio 2013 / 2015", - "url": "{{buildUrl}}", - "commit": "{{commitId}}", - "branch": "{{branch}}" - } - {{/isPullRequest}} - on_build_success: false - on_build_failure: true - on_build_status_changed: false diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index 01897e986e..0000000000 --- a/.cirrus.yml +++ /dev/null @@ -1,63 +0,0 @@ -# This CI is used to test Arm cases. We can set the maximum 16 tasks. -# The entire testing design is inspired from .github/workflows/compilers.yml. - -# By default, Cirrus mounts an empty volume to `/tmp` -# which triggers all sorts of warnings like "system temporary path is world-writable: /tmp". -# Lets workaround it by specifying a custom volume mount point. -env: - CIRRUS_VOLUME: /cirrus-ci-volume - LANG: C.UTF-8 - -task: - name: Arm64 Graviton2 / $CC - arm_container: - # We use the arm64 images at http://ghcr.io/ruby/ruby-ci-image . - image: ghcr.io/ruby/ruby-ci-image:$CC - # Define the used cpu core in each matrix task. We can use total 16 cpu - # cores in entire matrix. [cpu] = [total cpu: 16] / [number of tasks] - cpu: 8 - # We can request maximum 4 GB per cpu. - # [memory per task] = [memory per cpu: 4 GB] * [cpu] - memory: 32G - env: - CIRRUS_CLONE_DEPTH: 50 - optflags: '-O1' - debugflags: '-ggdb3' - RUBY_PREFIX: /tmp/ruby-prefix - RUBY_DEBUG: ci rgengc - RUBY_TESTOPTS: >- - -q - --color=always - --tty=no - matrix: - CC: clang-12 - CC: gcc-11 - id_script: id - set_env_script: - # Set `GNUMAKEFLAGS`, because the flags are GNU make specific. Note using - # the `make` environment variable used in compilers.yml causes some rubygems - # tests to fail. - # https://github.com/rubygems/rubygems/issues/4921 - - echo "GNUMAKEFLAGS=-s -j$((1 + $CIRRUS_CPU))" >> $CIRRUS_ENV - print_env_script: - - echo "GNUMAKEFLAGS=$GNUMAKEFLAGS" - # Arm containers are executed in AWS's EKS, and it's not yet supporting IPv6 - # See https://github.com/aws/containers-roadmap/issues/835 - disable_ipv6_script: sudo ./tool/disable_ipv6.sh - autogen_script: ./autogen.sh - configure_script: >- - ./configure -C - --enable-debug-env - --disable-install-doc - --with-ext=-test-/cxxanyargs,+ - --prefix="$RUBY_PREFIX" - make_extract-extlibs_script: make extract-extlibs - make_incs_script: make incs - make_script: make - make_leaked-globals_script: make leaked-globals - make_test_script: make test - make_install_script: make install - install_gems_for_test_script: $RUBY_PREFIX/bin/gem install --no-doc timezone tzinfo - make_test-tool_script: make test-tool - make_test-all_script: make test-all - make_test-spec_script: make test-spec @@ -15,15 +15,26 @@ array.rb ast.rb dir.rb gc.rb +hash.rb io.rb kernel.rb +marshal.rb numeric.rb nilclass.rb pack.rb +pathname_builtin.rb ractor.rb +string.rb +symbol.rb timev.rb +thread_sync.rb trace_point.rb warning.rb +yjit.rb +zjit.rb + +# Errno::* +known_errors.inc # the lib/ directory (which has its own .document file) lib @@ -39,11 +50,7 @@ README.ja.md COPYING COPYING.ja -CONTRIBUTING.md LEGAL -# win32/README.win32 linked from README.md -win32 - doc @@ -1,23 +1,7 @@ -set startup-with-shell off - -define hook-run - set $color_type = 0 - set $color_highlite = 0 - set $color_end = 0 -end - define ruby_gdb_init - if !$color_type - set $color_type = "\033[31m" - end - if !$color_highlite - set $color_highlite = "\033[36m" - end - if !$color_end - set $color_end = "\033[m" - end - if ruby_dummy_gdb_enums.special_consts - end + init-if-undefined $color_type = "\033[31m" + init-if-undefined $color_highlite = "\033[36m" + init-if-undefined $color_end = "\033[m" end # set prompt \033[36m(gdb)\033[m\040 @@ -67,7 +51,7 @@ define rp printf "%sT_OBJECT%s: ", $color_type, $color_end print ((struct RObject *)($arg0))->basic if ($flags & ROBJECT_EMBED) - print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (ROBJECT_EMBED_LEN_MAX+0) + print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (RSHAPE_CAPACITY(rb_obj_shape_id($arg0))) else print (((struct RObject *)($arg0))->as.heap) if (((struct RObject*)($arg0))->as.heap.numiv) > 0 @@ -99,13 +83,11 @@ define rp set $regsrc = ((struct RRegexp*)($arg0))->src set $rsflags = ((struct RBasic*)$regsrc)->flags printf "%sT_REGEXP%s: ", $color_type, $color_end - set $len = ($rsflags & RUBY_FL_USER1) ? \ - ((struct RString*)$regsrc)->as.heap.len : \ - (($rsflags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + set $len = ((struct RString*)($arg0))->len set print address off output *(char *)(($rsflags & RUBY_FL_USER1) ? \ - ((struct RString*)$regsrc)->as.heap.ptr : \ - ((struct RString*)$regsrc)->as.ary) @ $len + ((struct RString*)$regsrc)->as.heap.ptr : \ + ((struct RString*)$regsrc)->as.embed.ary) @ $len set print address on printf " len:%ld ", $len if $flags & RUBY_FL_USER6 @@ -126,26 +108,26 @@ define rp printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len printf "(embed) " if ($len == 0) - printf "{(empty)} " + printf "{(empty)} " else - print/x *((VALUE*)((struct RArray*)($arg0))->as.ary) @ $len - printf " " + print/x *((VALUE*)((struct RArray*)($arg0))->as.ary) @ $len + printf " " end else set $len = ((struct RArray*)($arg0))->as.heap.len printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len if ($flags & RUBY_FL_USER2) - printf "(shared) shared=" - output/x ((struct RArray*)($arg0))->as.heap.aux.shared_root - printf " " + printf "(shared) shared=" + output/x ((struct RArray*)($arg0))->as.heap.aux.shared_root + printf " " else - printf "(ownership) capa=%ld ", ((struct RArray*)($arg0))->as.heap.aux.capa + printf "(ownership) capa=%ld ", ((struct RArray*)($arg0))->as.heap.aux.capa end if ($len == 0) - printf "{(empty)} " + printf "{(empty)} " else - print/x *((VALUE*)((struct RArray*)($arg0))->as.heap.ptr) @ $len - printf " " + print/x *((VALUE*)((struct RArray*)($arg0))->as.heap.ptr) @ $len + printf " " end end print (struct RArray *)($arg0) @@ -157,13 +139,15 @@ define rp if ($flags & RUBY_T_MASK) == RUBY_T_HASH printf "%sT_HASH%s: ", $color_type, $color_end, if (((struct RHash *)($arg0))->basic.flags & RHASH_ST_TABLE_FLAG) - printf "st len=%ld ", ((struct RHash *)($arg0))->as.st->num_entries + set $st = (struct st_table *)((uintptr_t)($arg0) + sizeof(struct RHash)) + printf "st len=%ld ", $st->num_entries + print $st else printf "li len=%ld bound=%ld ", \ ((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_SIZE_MASK) >> RHASH_AR_TABLE_SIZE_SHIFT), \ ((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_BOUND_MASK) >> RHASH_AR_TABLE_BOUND_SHIFT) + print (struct ar_table_struct *)((uintptr_t)($arg0) + sizeof(struct RHash)) end - print (struct RHash *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_STRUCT set $len = (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \ @@ -201,12 +185,19 @@ define rp print (struct RBasic *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_DATA - if ((struct RTypedData *)($arg0))->typed_flag == 1 - printf "%sT_DATA%s(%s): ", $color_type, $color_end, ((struct RTypedData *)($arg0))->type->wrap_struct_name - print (struct RTypedData *)($arg0) + if ($flags & RUBY_TYPED_FL_IS_TYPED_DATA) + set $data = (struct RTypedData *)($arg0) + set $type = (const rb_data_type_t *)($data->type & ~1) + printf "%sT_DATA%s(%s): ", $color_type, $color_end, $type->wrap_struct_name + print *$type + if ($data->type & 1) + print (void *)&$data->data + else + print $data + end else printf "%sT_DATA%s: ", $color_type, $color_end - print (struct RData *)($arg0) + print *(struct RData *)($arg0) end else if ($flags & RUBY_T_MASK) == RUBY_T_MATCH @@ -440,13 +431,11 @@ end define output_string set $flags = ((struct RBasic*)($arg0))->flags - set $len = ($flags & RUBY_FL_USER1) ? \ - ((struct RString*)($arg0))->as.heap.len : \ - (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + set $len = ((struct RString*)($arg0))->len if $len > 0 output *(char *)(($flags & RUBY_FL_USER1) ? \ - ((struct RString*)($arg0))->as.heap.ptr : \ - ((struct RString*)($arg0))->as.ary) @ $len + ((struct RString*)($arg0))->as.heap.ptr : \ + ((struct RString*)($arg0))->as.embed.ary) @ $len else output "" end @@ -454,13 +443,11 @@ end define print_string set $flags = ((struct RBasic*)($arg0))->flags - set $len = ($flags & RUBY_FL_USER1) ? \ - ((struct RString*)($arg0))->as.heap.len : \ - (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + set $len = ((struct RString*)($arg0))->len if $len > 0 printf "%s", *(char *)(($flags & RUBY_FL_USER1) ? \ - ((struct RString*)($arg0))->as.heap.ptr : \ - ((struct RString*)($arg0))->as.ary) @ $len + ((struct RString*)($arg0))->as.heap.ptr : \ + ((struct RString*)($arg0))->as.embed.ary) @ $len end end @@ -543,14 +530,14 @@ document rp_bignum end define rp_class + set $class_and_classext = (struct RClass_and_rb_classext_t *)($arg0) printf "(struct RClass *) %p", (void*)$arg0 - if ((struct RClass *)($arg0))->ptr.origin_ != $arg0 - printf " -> %p", ((struct RClass *)($arg0))->ptr.origin_ + if $class_and_classext->classext->origin_ != (VALUE)$arg0 + printf " -> %p", $class_and_classext->classext->origin_ end printf "\n" rb_classname $arg0 - print/x *(struct RClass *)($arg0) - print *((struct RClass *)($arg0))->ptr + print/x *$class_and_classext end document rp_class Print the content of a Class/Module. @@ -689,11 +676,6 @@ define nd_stts end -define nd_entry - printf "%su3.entry%s: ", $color_highlite, $color_end - p ($arg0).u3.entry -end - define nd_vid printf "%su1.id%s: ", $color_highlite, $color_end p ($arg0).u1.id @@ -868,22 +850,22 @@ define rb_numtable_entry set $rb_numtable_p = $rb_numtable_tbl->as.packed.bins while $rb_numtable_p && $rb_numtable_p < $rb_numtable_tbl->as.packed.bins+$rb_numtable_tbl->num_entries if $rb_numtable_p.k == $rb_numtable_id - set $rb_numtable_key = $rb_numtable_p.k - set $rb_numtable_rec = $rb_numtable_p.v - set $rb_numtable_p = 0 + set $rb_numtable_key = $rb_numtable_p.k + set $rb_numtable_rec = $rb_numtable_p.v + set $rb_numtable_p = 0 else - set $rb_numtable_p = $rb_numtable_p + 1 + set $rb_numtable_p = $rb_numtable_p + 1 end end else set $rb_numtable_p = $rb_numtable_tbl->as.big.bins[st_numhash($rb_numtable_id) % $rb_numtable_tbl->num_bins] while $rb_numtable_p if $rb_numtable_p->key == $rb_numtable_id - set $rb_numtable_key = $rb_numtable_p->key - set $rb_numtable_rec = $rb_numtable_p->record - set $rb_numtable_p = 0 + set $rb_numtable_key = $rb_numtable_p->key + set $rb_numtable_rec = $rb_numtable_p->record + set $rb_numtable_p = 0 else - set $rb_numtable_p = $rb_numtable_p->next + set $rb_numtable_p = $rb_numtable_p->next end end end @@ -921,10 +903,10 @@ document rb_method_entry end define rb_classname - # up to 128bit int - set $rb_classname = rb_mod_name($arg0) - if $rb_classname != RUBY_Qnil - rp $rb_classname + set $rb_classname = ((struct RClass_and_rb_classext_t*)$arg0)->classext->classpath + if $rb_classname != RUBY_Qfalse + print_string $rb_classname + printf "\n" else echo anonymous class/module\n end @@ -961,7 +943,7 @@ define iseq set $operand_size = ((INSN*)($arg0))->operand_size set $operands = ((INSN*)($arg0))->operands while $i < $operand_size - rp $operands[$i++] + rp $operands[$i++] end end end @@ -979,8 +961,8 @@ end define rb_ps_vm print $ps_vm = (rb_vm_t*)$arg0 - set $ps_thread_ln = $ps_vm->living_threads.n.next - set $ps_thread_ln_last = $ps_vm->living_threads.n.prev + set $ps_thread_ln = $ps_vm->ractor.main_ractor.threads.set.n.next + set $ps_thread_ln_last = $ps_vm->ractor.main_ractor.threads.set.n.prev while 1 set $ps_thread_th = (rb_thread_t *)$ps_thread_ln set $ps_thread = (VALUE)($ps_thread_th->self) @@ -1131,7 +1113,7 @@ define rb_ps_thread set $ps_thread = (struct RTypedData*)$arg0 set $ps_thread_th = (rb_thread_t*)$ps_thread->data printf "* #<Thread:%p rb_thread_t:%p native_thread:%p>\n", \ - $ps_thread, $ps_thread_th, $ps_thread_th->thread_id + $ps_thread, $ps_thread_th, $ps_thread_th->nt set $cfp = $ps_thread_th->ec->cfp set $cfpend = (rb_control_frame_t *)($ps_thread_th->ec->vm_stack + $ps_thread_th->ec->vm_stack_size)-1 while $cfp < $cfpend @@ -1279,9 +1261,9 @@ document rb_count_objects Counts all objects grouped by type. end -# Details: https://bugs.ruby-lang.org/projects/ruby-master/wiki/MachineInstructionsTraceWithGDB +# Details: https://github.com/ruby/ruby/wiki/Machine-Instructions-Trace-with-GDB define trace_machine_instructions - set logging on + set logging enabled set height 0 set width 0 display/i $pc @@ -1316,13 +1298,12 @@ define dump_node set $flags = ((struct RBasic*)($str))->flags printf "%s", (char *)(($flags & RUBY_FL_USER1) ? \ ((struct RString*)$str)->as.heap.ptr : \ - ((struct RString*)$str)->as.ary) + ((struct RString*)$str)->as.embed.ary) end define print_flags printf "RUBY_FL_WB_PROTECTED: %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_WB_PROTECTED ? "1" : "0" - printf "RUBY_FL_PROMOTED0 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED0 ? "1" : "0" - printf "RUBY_FL_PROMOTED1 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED1 ? "1" : "0" + printf "RUBY_FL_PROMOTED : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED ? "1" : "0" printf "RUBY_FL_FINALIZE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_FINALIZE ? "1" : "0" printf "RUBY_FL_SHAREABLE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_SHAREABLE ? "1" : "0" printf "RUBY_FL_EXIVAR : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_EXIVAR ? "1" : "0" @@ -1348,3 +1329,8 @@ define print_flags printf "RUBY_FL_USER17 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER17 ? "1" : "0" printf "RUBY_FL_USER18 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER18 ? "1" : "0" end + +source -s misc/gdb.py + +# Moved from beginning, since it fails on older gdbs +set startup-with-shell off diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..d98646febf --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,41 @@ +# This is a file used by GitHub to ignore the following commits on `git blame`. +# +# You can also do the same thing in your local repository with: +# $ git config --local blame.ignoreRevsFile .git-blame-ignore-revs + +# Expand tabs +5b21e94bebed90180d8ff63dad03b8b948361089 +c5e9af9c9d890578182a21e7b71b50334cd5579e +e63a2115f64433b21cb5dd67c5bf8b30f87ef293 +712ac99e4d0384a941c80a9f48f62943ba7d97c0 +d1474affa8e105bece209cc9d594bb0a989859e1 +2da92388b948821269b18d6b178a680f17e41750 +5062c0c621d887367af8a054e5e5d83d7ec57dd3 + +# Enable Style/StringLiterals cop for RubyGems/Bundler +d7ffd3fea402239b16833cc434404a7af82d44f3 + +# [ruby/digest] Revert tab-expansion in external files +48b09aae7ec5632209229dcc294dd0d75a93a17f +8a65cf3b61c60e4cb886f59a73ff6db44364bfa9 +39dc9f9093901d40d2998653948d5da38b18ee2c + +# [ruby/io-nonblock] Revert tab expansion +f28287d34c03f472ffe90ea262bdde9affd4b965 +0d842fecb4f75ab3b1d4097ebdb8e88f51558041 +4ba2c66761d6a293abdfba409241d31063cefd62 + +# Make benchmark indentation consistent +fc4acf8cae82e5196186d3278d831f2438479d91 + +# Make prism_compile.c indentation consistent +40b2c8e5e7e6e5f83cee9276dc9c1922a69292d6 +d2c5867357ed88eccc28c2b3bd4a46e206e7ff85 + +# Miss-and-revived commits +a0f7de814ae5c299d6ce99bed5fb308a05d50ba0 +d4e24021d39e1f80f0055b55d91f8d5f22e15084 +7a56c316418980b8a41fcbdc94067b2bda2ad112 +e90282be7ba1bc8e3119f6e1a2c80356ceb3f80a +26a9e0b4e31f7b5a9cbd755e0a15823a8fa51bae +2f53985da9ee593fe524d408256835667938c7d7 diff --git a/.gitattributes b/.gitattributes index d0c2d266b4..6ac6e6fcc3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ *.gemspec diff=ruby *.rb diff=ruby +*.inc.rs linguist-generated=true bin svn-properties=svn:ignore=ruby bin/* diff=ruby tool/update-deps diff=ruby diff --git a/.github/actions/capiext/action.yml b/.github/actions/capiext/action.yml new file mode 100644 index 0000000000..49562725f4 --- /dev/null +++ b/.github/actions/capiext/action.yml @@ -0,0 +1,86 @@ +name: rubyspec C-API extensions + +inputs: + builddir: + required: false + default: '.' + make: + required: false + default: 'make -s' + +outputs: + key: + value: >- + ${{ + !steps.restore.outputs.cache-hit && + github.ref == 'refs/heads/master' && + steps.config.outputs.key + }} + +runs: + using: composite + + steps: + - id: config + shell: bash + run: | + eval $(grep -e '^arch *=' -e '^ruby_version *=' -e '^DLEXT *=' Makefile | + sed 's/ *= */=/') + case "${ruby_version}" in + *+*) key=capiexts-${arch}-${ruby_version}-${{ hashFiles('src/spec/ruby/optional/capi/ext/*.[ch]') }};; + *) key=;; + esac + echo version=$ruby_version >> $GITHUB_OUTPUT + echo key="$key" >> $GITHUB_OUTPUT + echo DLEXT=$DLEXT >> $GITHUB_OUTPUT + working-directory: ${{ inputs.builddir }} + + - name: Restore previous CAPI extensions + uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + id: cache + with: + path: ${{ inputs.builddir }}/spec/ruby/optional/capi/ext/ + key: ${{ steps.config.outputs.key }} + if: ${{ steps.config.outputs.key }} + + - name: Run test-spec with previous CAPI extension binaries + id: check + shell: bash + run: | + touch spec/ruby/optional/capi/ext/*.$DLEXT + [ ! -f spec/ruby/optional/capi/ext/\*.$DLEXT ] + ${{ inputs.make }} SPECOPTS=optional/capi test-spec + env: + DLEXT: ${{ steps.config.outputs.DLEXT }} + working-directory: ${{ inputs.builddir }} + if: ${{ steps.cache.outputs.cache-hit }} + + - name: Strip CAPI extensions + id: strip + shell: bash + run: | + rm -f spec/ruby/optional/capi/ext/*.c + [ "$DLEXT" = bundle ] || # separated to .dSYM directories + strip spec/ruby/optional/capi/ext/*.$DLEXT + env: + DLEXT: ${{ steps.config.outputs.DLEXT }} + working-directory: ${{ inputs.builddir }} + if: >- + ${{true + && ! steps.cache.outputs.cache-hit + && github.ref_name == 'master' + }} + + - name: Save CAPI extensions + uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + with: + path: ${{ inputs.builddir }}/spec/ruby/optional/capi/ext/ + key: ${{ steps.config.outputs.key }} + if: ${{ steps.strip.outcome == 'success' }} + + - shell: bash + run: | + echo "::error::Change from ${prev} detected; bump up ABI version" + env: + prev: ${{ steps.config.outputs.version }} + if: ${{ always() && steps.check.outcome == 'failure' }} diff --git a/.github/actions/compilers/action.yml b/.github/actions/compilers/action.yml new file mode 100644 index 0000000000..ab5b56a889 --- /dev/null +++ b/.github/actions/compilers/action.yml @@ -0,0 +1,133 @@ +name: Compiles ruby in a container +description: >- + Makes ruby using a dedicated container + +inputs: + tag: + required: false + default: clang-20 + description: >- + container image tag to use in this run. + + with_gcc: + required: false + description: >- + override compiler path & flags. + + CFLAGS: + required: false + description: >- + C compiler flags to override. + + CXXFLAGS: + required: false + description: >- + C++ compiler flags to override. + + optflags: + required: false + # -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. + default: '-O1' + description: >- + Compiler flags for optimisations. + + cppflags: + required: false + description: >- + Additional preprocessor flags. + + append_configure: + required: false + default: >- + --without-valgrind + --without-jemalloc + --without-gmp + description: >- + flags to append to configure. + + enable_shared: + required: false + default: true + description: >- + Whether to build libruby.so. + + check: + required: false + default: '' + description: >- + Whether to run `make check` + + test_all: + required: false + default: '' + description: >- + Whether to run `make test-all` with options for test-all. + + test_spec: + required: false + default: '' + description: >- + Whether to run `make test-spec` with options for mspec. + + static_exts: + required: false + description: >- + whitespace separated list of extensions that need be linked statically. + +runs: + using: composite + steps: + - shell: bash + run: docker pull --quiet 'ghcr.io/ruby/ruby-ci-image:${{ inputs.tag }}' + + - name: Enable Launchable conditionally + id: enable-launchable + run: echo "enable-launchable=true" >> $GITHUB_OUTPUT + shell: bash + if: >- + ${{ + github.repository == 'ruby/ruby' || + (github.repository != 'ruby/ruby' && env.LAUNCHABLE_TOKEN) + }} + + - name: compile + shell: bash + run: >- + docker run + --rm + --user=root + --volume '${{ github.workspace }}:/github/workspace:ro' + --workdir=/github/workspace + --entrypoint=/github/workspace/.github/actions/compilers/entrypoint.sh + --env CI + --env GITHUB_ACTION + --env INPUT_WITH_GCC='${{ inputs.with_gcc || inputs.tag }}' + --env INPUT_CFLAGS='${{ inputs.CFLAGS }}' + --env INPUT_CXXFLAGS='${{ inputs.CXXFLAGS }}' + --env INPUT_OPTFLAGS='${{ inputs.OPTFLAGS }}' + --env INPUT_CPPFLAGS='${{ inputs.cppflags }}' + --env INPUT_APPEND_CONFIGURE='${{ inputs.append_configure }}' + --env INPUT_CHECK='${{ inputs.check }}' + --env INPUT_TEST_ALL='${{ inputs.test_all }}' + --env INPUT_TEST_SPEC='${{ inputs.test_spec }}' + --env INPUT_ENABLE_SHARED='${{ inputs.enable_shared }}' + --env INPUT_STATIC_EXTS='${{ inputs.static_exts }}' + --env LAUNCHABLE_ORGANIZATION='${{ github.repository_owner }}' + --env LAUNCHABLE_WORKSPACE='${{ github.event.repository.name }}' + --env LAUNCHABLE_ENABLED='${{ steps.enable-launchable.outputs.enable-launchable || false }}' + --env GITHUB_PR_HEAD_SHA='${{ github.event.pull_request.head.sha || github.sha }}' + --env GITHUB_PULL_REQUEST_URL='${{ github.event.pull_request.html_url }}' + --env GITHUB_REF='${{ github.ref }}' + --env GITHUB_ACTIONS + --env GITHUB_RUN_ID + --env GITHUB_REPOSITORY + --env GITHUB_WORKFLOW + --env GITHUB_RUN_NUMBER + --env GITHUB_EVENT_NAME + --env GITHUB_SHA + --env GITHUB_HEAD_REF + --env GITHUB_SERVER_URL + 'ghcr.io/ruby/ruby-ci-image:${{ inputs.tag }}' diff --git a/.github/actions/compilers/entrypoint.sh b/.github/actions/compilers/entrypoint.sh new file mode 100755 index 0000000000..b554151091 --- /dev/null +++ b/.github/actions/compilers/entrypoint.sh @@ -0,0 +1,90 @@ +#! /bin/bash + +# Copyright (c) 2024 Ruby developers. All rights reserved. +# +# This file is a part of the programming language Ruby. Permission is hereby +# granted, to either redistribute and/or modify this file, provided that the +# conditions mentioned in the file COPYING are met. Consult the file for +# details. + +grouped() +{ + echo "::group::${@}" + "${@}" + echo "::endgroup::" +} + +set -e +set -u +set -o pipefail + +srcdir="/github/workspace/src" +builddir="$(mktemp -dt)" + +export GITHUB_WORKFLOW='Compilations' +export CONFIGURE_TTY='never' +export RUBY_DEBUG='ci rgengc' +export RUBY_TESTOPTS='-q --color=always --tty=no' +export RUBY_DEBUG_COUNTER_DISABLE='1' +export GNUMAKEFLAGS="-j$((1 + $(nproc)))" + +case "x${INPUT_ENABLE_SHARED}" in +x | xno | xfalse ) + enable_shared='--disable-shared' + ;; +*) + enable_shared='--enable-shared' + ;; +esac + +pushd ${builddir} + +grouped git config --global --add safe.directory ${srcdir} + +grouped ${srcdir}/configure \ + -C \ + --with-gcc="${INPUT_WITH_GCC}" \ + --enable-debug-env \ + --disable-install-doc \ + --with-ext=-test-/cxxanyargs,+ \ + --without-git \ + ${enable_shared} \ + ${INPUT_APPEND_CONFIGURE} \ + CFLAGS="${INPUT_CFLAGS}" \ + CXXFLAGS="${INPUT_CXXFLAGS}" \ + optflags="${INPUT_OPTFLAGS}" \ + cppflags="${INPUT_CPPFLAGS}" \ + debugflags='-ggdb3' # -g0 disables backtraces when SEGV. Do not set that. + +popd + +if [[ -n "${INPUT_STATIC_EXTS}" ]]; then + echo "::group::ext/Setup" + set -x + mkdir ${builddir}/ext + ( + for ext in ${INPUT_STATIC_EXTS}; do + echo "${ext}" + done + ) >> ${builddir}/ext/Setup + set +x + echo "::endgroup::" +fi + +if [ -n "$INPUT_TEST_ALL" ]; then + tests=" -- $INPUT_TEST_ALL" +else + tests=" -- ruby -ext-" +fi + +pushd ${builddir} + +grouped make showflags +grouped make all +# grouped make install + +# Run only `make test` by default. Run other tests if specified. +grouped make test +if [[ -n "$INPUT_CHECK" ]]; then grouped make test-tool; fi +if [[ -n "$INPUT_CHECK" || -n "$INPUT_TEST_ALL" ]]; then grouped make test-all TESTS="$tests"; fi +if [[ -n "$INPUT_CHECK" || -n "$INPUT_TEST_SPEC" ]]; then grouped env CHECK_LEAKS=true make test-spec MSPECOPT="$INPUT_TEST_SPEC"; fi diff --git a/.github/actions/launchable/setup/action.yml b/.github/actions/launchable/setup/action.yml new file mode 100644 index 0000000000..16af8fc3fd --- /dev/null +++ b/.github/actions/launchable/setup/action.yml @@ -0,0 +1,313 @@ +name: Set up Launchable +description: >- + Install the required dependencies and execute the necessary Launchable commands for test recording + +inputs: + os: + required: true + description: The operating system that CI runs on. This value is used in Launchable flavor. + + test-opts: + default: none + required: false + description: >- + Test options that determine how tests are run. + This value is used in the Launchable flavor. + + launchable-token: + required: false + description: >- + Launchable token is needed if you want to run Launchable on your forked repository. + See https://github.com/ruby/ruby/wiki/CI-Servers#launchable-ci for details. + + builddir: + required: false + default: ${{ github.workspace }} + description: >- + Directory to create Launchable report file. + + srcdir: + required: false + default: ${{ github.workspace }} + description: >- + Directory to (re-)checkout source codes. Launchable retrieves the commit information + from the directory. + + test-task: + required: false + default: ${{ matrix.test_task }} + description: >- + Specifies a single test task to be executed. + This value is used in the Launchable flavor. + Either 'test-task' or 'multi-test-tasks' must be configured. + + test-tasks: + required: false + default: '[]' + description: >- + Specifies an array of multiple test tasks to be executed. + For example: '["test", "test-all"]'. + If you want to run a single test task, use the 'test-task' input instead. + + is-yjit: + required: false + default: 'false' + description: >- + Whether this workflow is executed on YJIT. + +outputs: + stdout_report_path: + value: ${{ steps.global.outputs.stdout_report_path }} + description: >- + Report file path for standard output. + + stderr_report_path: + value: ${{ steps.global.outputs.stderr_report_path }} + description: >- + Report file path for standard error. + +runs: + using: composite + + steps: + - name: Enable Launchable conditionally + id: enable-launchable + run: echo "enable-launchable=true" >> $GITHUB_OUTPUT + shell: bash + if: >- + ${{ + (github.repository == 'ruby/ruby' + || (github.repository != 'ruby/ruby' + && env.LAUNCHABLE_TOKEN)) + && (inputs.test-task == 'check' + || inputs.test-task == 'test-all' + || inputs.test-task == 'test' + || contains(fromJSON(inputs.test-tasks), 'test-all') + || contains(fromJSON(inputs.test-tasks), 'test')) + }} + + # Launchable CLI requires Python and Java. + # https://www.launchableinc.com/docs/resources/cli-reference/ + - name: Set up Python + uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0 + with: + python-version: "3.x" + if: >- + ${{ steps.enable-launchable.outputs.enable-launchable + && !endsWith(inputs.os, 'ppc64le') && !endsWith(inputs.os, 's390x') }} + + - name: Set up Java + uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0 + with: + distribution: 'temurin' + java-version: '17' + if: >- + ${{ steps.enable-launchable.outputs.enable-launchable + && !endsWith(inputs.os, 'ppc64le') && !endsWith(inputs.os, 's390x') }} + + - name: Set up Java ppc64le + uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0 + with: + distribution: 'semeru' + architecture: 'ppc64le' + java-version: '17' + if: >- + ${{ steps.enable-launchable.outputs.enable-launchable + && endsWith(inputs.os, 'ppc64le') }} + + - name: Set up Java s390x + uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0 + with: + distribution: 'semeru' + architecture: 's390x' + java-version: '17' + if: >- + ${{ steps.enable-launchable.outputs.enable-launchable + && endsWith(inputs.os, 's390x') }} + + - name: Set global vars + id: global + shell: bash + run: | + test_all_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test-all' || contains(fromJSON(inputs.test-tasks), 'test-all') }}" + btest_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test' || contains(fromJSON(inputs.test-tasks), 'test') }}" + test_spec_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test-spec' || contains(fromJSON(inputs.test-tasks), 'test-spec') }}" + echo test_all_enabled="${test_all_enabled}" >> $GITHUB_OUTPUT + echo btest_enabled="${btest_enabled}" >> $GITHUB_OUTPUT + echo test_spec_enabled="${test_spec_enabled}" >> $GITHUB_OUTPUT + echo test_all_report_file='launchable_test_all_report.json' >> $GITHUB_OUTPUT + echo btest_report_file='launchable_btest_report.json' >> $GITHUB_OUTPUT + echo test_spec_report_dir='launchable_test_spec_report' >> $GITHUB_OUTPUT + echo stdout_report_path="launchable_stdout.log" >> $GITHUB_OUTPUT + echo stderr_report_path="launchable_stderr.log" >> $GITHUB_OUTPUT + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set environment variables for Launchable + shell: bash + run: | + : # GITHUB_PULL_REQUEST_URL are used for commenting test reports in Launchable Github App. + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/link.py#L42 + echo "GITHUB_PULL_REQUEST_URL=${{ github.event.pull_request.html_url }}" >> $GITHUB_ENV + : # The following envs are necessary in Launchable tokenless authentication. + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L20 + echo "LAUNCHABLE_ORGANIZATION=${{ github.repository_owner }}" >> $GITHUB_ENV + echo "LAUNCHABLE_WORKSPACE=${{ github.event.repository.name }}" >> $GITHUB_ENV + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L71 + echo "GITHUB_PR_HEAD_SHA=${{ github.event.pull_request.head.sha || github.sha }}" >> $GITHUB_ENV + echo "LAUNCHABLE_TOKEN=${{ inputs.launchable-token }}" >> $GITHUB_ENV + : # To prevent a slowdown in CI, disable request retries when the Launchable server is unstable. + echo "LAUNCHABLE_SKIP_TIMEOUT_RETRY=1" >> $GITHUB_ENV + echo "LAUNCHABLE_COMMIT_TIMEOUT=1" >> $GITHUB_ENV + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set up path + shell: bash + working-directory: ${{ inputs.srcdir }} + # Since updated PATH variable will be available in only subsequent actions, we need to add the path beforehand. + # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path + run: echo "$(python -msite --user-base)/bin" >> $GITHUB_PATH + if: >- + ${{ + steps.enable-launchable.outputs.enable-launchable + && (startsWith(inputs.os, 'macos') + || endsWith(inputs.os, 'ppc64le') + || endsWith(inputs.os, 's390x')) + }} + + - name: Set up Launchable + id: setup-launchable + shell: bash + working-directory: ${{ inputs.srcdir }} + run: | + set -x + pip install --user launchable + : # The build name cannot include a slash, so we replace the string here. + github_ref="${{ github.ref }}" + github_ref="${github_ref//\//_}" + : # With the --name option, we need to configure a unique identifier for this build. + : # To avoid setting the same build name as the CI which runs on other branches, we use the branch name here. + build_name="${github_ref}_${GITHUB_PR_HEAD_SHA}" + test_opts="${{ inputs.test-opts }}" + test_opts="${test_opts// /}" + test_opts="${test_opts//=/:}" + test_all_test_suite='test-all' + btest_test_suite='btest' + test_spec_test_suite='test-spec' + if [ "${{ inputs.is-yjit }}" = "true" ]; then + test_all_test_suite="yjit-${test_all_test_suite}" + btest_test_suite="yjit-${btest_test_suite}" + test_spec_test_suite="yjit-${test_spec_test_suite}" + fi + # launchable_setup target var -- refers ${target} prefixed variables + launchable_setup() { + local target=$1 session + eval [ "\${${target}_enabled}" = "true" ] || return + eval local suite=\${${target}_test_suite} + session=$(launchable record session \ + --build "${build_name}" \ + --observation \ + --flavor os="${{ inputs.os }}" \ + --flavor test_task="${{ inputs.test-task }}" \ + --flavor test_opts="${test_opts}" \ + --flavor workflow="${{ github.workflow }}" \ + --test-suite ${suite} \ + ) + echo "${target}_session=${session}" >> $GITHUB_OUTPUT + } + + launchable record build --name "${build_name}" + if launchable_setup test_all; then + echo "TESTS=${TESTS:+$TESTS }--launchable-test-reports=${test_all_report_file}" >> $GITHUB_ENV + fi + if launchable_setup btest; then + echo "BTESTS=${BTESTS:+$BTESTS }--launchable-test-reports=${btest_report_file}" >> $GITHUB_ENV + fi + if launchable_setup test_spec; then + echo "SPECOPTS=${SPECOPTS:$SPECOPTS }--launchable-test-reports=${test_spec_report_dir}" >> $GITHUB_ENV + echo test_spec_enabled=true >> $GITHUB_OUTPUT + fi + + echo launchable_setup_dir=$(pwd) >> $GITHUB_OUTPUT + if: steps.enable-launchable.outputs.enable-launchable + env: + test_all_enabled: ${{ steps.global.outputs.test_all_enabled }} + btest_enabled: ${{ steps.global.outputs.btest_enabled }} + test_spec_enabled: ${{ steps.global.outputs.test_spec_enabled }} + test_all_report_file: ${{ steps.global.outputs.test_all_report_file }} + btest_report_file: ${{ steps.global.outputs.btest_report_file }} + test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }} + + - name: make test-spec report directory in build directory + shell: bash + working-directory: ${{ inputs.builddir }} + run: mkdir "${test_spec_report_dir}" + if: ${{ steps.setup-launchable.outputs.test_spec_enabled == 'true' }} + env: + test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }} + + - name: Clean up test results in Launchable + uses: gacts/run-and-post-run@674528335da98a7afc80915ff2b4b860a0b3553a # v1.4.0 + with: + shell: bash + working-directory: ${{ inputs.builddir }} + post: | + rm -f "${test_all_report_file}" + rm -f "${btest_report_file}" + rm -fr "${test_spec_report_dir}" + rm -f launchable_stdout.log + rm -f launchable_stderr.log + if: always() && steps.setup-launchable.outcome == 'success' + env: + test_all_report_file: ${{ steps.global.outputs.test_all_report_file }} + btest_report_file: ${{ steps.global.outputs.btest_report_file }} + test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }} + + - name: Record test results in Launchable + uses: gacts/run-and-post-run@674528335da98a7afc80915ff2b4b860a0b3553a # v1.4.0 + with: + shell: bash + working-directory: ${{ inputs.builddir }} + post: | + if [[ "${test_all_enabled}" = "true" ]]; then \ + launchable record attachment \ + --session "${test_all_session}" \ + "${stdout_report_path}" \ + "${stderr_report_path}"; \ + launchable record tests \ + --session "${test_all_session}" \ + raw "${test_all_report_file}" || true; \ + fi + + if [[ "${btest_enabled}" = "true" ]]; then \ + launchable record attachment \ + --session "${btest_session}" \ + "${stdout_report_path}" \ + "${stderr_report_path}"; \ + launchable record tests \ + --session "${btest_session}" \ + raw "${btest_report_file}" || true; \ + fi + + if [[ "${test_spec_enabled}" = "true" ]]; then \ + launchable record attachment \ + --session "${test_spec_session}" \ + "${stdout_report_path}" \ + "${stderr_report_path}"; \ + launchable record tests \ + --session "${test_spec_session}" \ + raw ${test_spec_report_dir}/* || true; \ + fi + if: ${{ always() && steps.setup-launchable.outcome == 'success' }} + env: + test_all_report_file: ${{ steps.global.outputs.test_all_report_file }} + btest_report_file: ${{ steps.global.outputs.btest_report_file }} + test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }} + test_all_enabled: ${{ steps.global.outputs.test_all_enabled }} + btest_enabled: ${{ steps.global.outputs.btest_enabled }} + test_spec_enabled: ${{ steps.global.outputs.test_spec_enabled }} + test_all_session: ${{ steps.setup-launchable.outputs.test_all_session }} + btest_session: ${{ steps.setup-launchable.outputs.btest_session }} + test_spec_session: ${{ steps.setup-launchable.outputs.test_spec_session }} + stdout_report_path: ${{ steps.global.outputs.stdout_report_path }} + stderr_report_path: ${{ steps.global.outputs.stderr_report_path }} + LAUNCHABLE_SETUP_DIR: ${{ steps.setup-launchable.outputs.launchable_setup_dir }} diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml new file mode 100644 index 0000000000..0e8ffd59ef --- /dev/null +++ b/.github/actions/setup/directories/action.yml @@ -0,0 +1,194 @@ +name: Setup directories etc. +description: >- + Set up the source code and build directories (plus some + environmental tweaks) + +inputs: + srcdir: + required: false + default: ${{ github.workspace }} + description: >- + Directory to (re-)checkout source codes. This will be created + if absent. If there is no `configure` file that is also + generated inside. + + builddir: + required: false + default: ${{ github.workspace }} + description: >- + Where binaries and other generated contents go. This will be + created if absent. + + make-command: + required: false + type: string + default: 'make' + description: >- + The command of `make`. + + makeup: + required: false + type: boolean + # Note that `default: false` evaluates to a string constant + # `'false'`, which is a truthy value :sigh: + # https://github.com/actions/runner/issues/2238 + default: '' + description: >- + If set to true, additionally runs `make up`. + + checkout: + required: false + type: boolean + default: true + description: >- + If set to '' (false), skip running actions/checkout. This is useful when + you don't want to overwrite a GitHub token that is already set up. + + dummy-files: + required: false + type: boolean + default: '' + description: >- + If set to true, creates dummy files in build dir. + + fetch-depth: + required: false + default: '1' + description: The depth of commit history fetched from the remote repository + + clean: + required: false + type: boolean + default: '' + description: >- + If set to true, clean build directory. + +outputs: {} # nothing? + +runs: + using: composite + + steps: + # Note that `shell: bash` works on both Windows and Linux, but not + # `shell: sh`. This is because GitHub hosted Windows runners have + # their bash manually installed. + - shell: bash + run: | + mkdir -p ${{ inputs.srcdir }} + mkdir -p ${{ inputs.builddir }} + + # Did you know that actions/checkout works without git(1)? We are + # checking that here. + - id: which + shell: bash + run: | + echo "git=`command -v git`" >> "$GITHUB_OUTPUT" + echo "sudo=`sudo true && command -v sudo`" >> "$GITHUB_OUTPUT" + echo "autoreconf=`command -v autoreconf`" >> "$GITHUB_OUTPUT" + + - if: steps.which.outputs.git + shell: bash + run: | + git config --global core.autocrlf false + git config --global core.eol lf + git config --global advice.detachedHead 0 + git config --global init.defaultBranch garbage + + - if: inputs.checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + path: ${{ inputs.srcdir }} + fetch-depth: ${{ inputs.fetch-depth }} + + - uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + with: + path: ${{ inputs.srcdir }}/.downloaded-cache + key: ${{ runner.os }}-${{ runner.arch }}-downloaded-cache + + - if: steps.which.outputs.autoreconf + shell: bash + working-directory: ${{ inputs.srcdir }} + run: ./autogen.sh --install + + # This is for MinGW. + - if: runner.os == 'Windows' + shell: bash + run: echo "GNUMAKEFLAGS=-j$((2 * NUMBER_OF_PROCESSORS))" >> $GITHUB_ENV + + - if: runner.os == 'Linux' + shell: bash + run: echo "GNUMAKEFLAGS=-sj$((1 + $(nproc)))" >> "$GITHUB_ENV" + + # macOS' GNU make is so old that they doesn't understand `GNUMAKEFLAGS`. + - if: runner.os == 'macOS' + shell: bash + run: echo "MAKEFLAGS=-j$((1 + $(sysctl -n hw.activecpu)))" >> "$GITHUB_ENV" + + - if: inputs.makeup + shell: bash + working-directory: ${{ inputs.srcdir }} + run: | + touch config.status .rbconfig.time + for mk in Makefile GNUmakefile; do + sed -f tool/prereq.status template/$mk.in > $mk + done + make up + + # Cleanup, runs even on failure + - if: always() && inputs.makeup + shell: bash + working-directory: ${{ inputs.srcdir }} + run: | + rm -f config.status .rbconfig.time \ + Makefile GNUmakefile uncommon.mk enc.mk noarch-fake.rb + + - if: steps.which.outputs.sudo + shell: bash + run: | + sudo chmod -R go-w /usr/share + chmod -v go-w $HOME $HOME/.config || : + declare -a dirs # -A is not supported by old bash, e.g. macos + SAVE_IFS="$IFS" IFS=:; set $PATH + for d do + while [ -d "$d" ]; do + case "$IFS${dirs[*]}$IFS" in *"$IFS$d$IFS"*) ;; *) dirs+=("$d");; esac + d="${d%/*}" + done + done + IFS="$SAVE_IFS" + sudo chmod -v go-w "${dirs[@]}" || : + + - if: inputs.dummy-files == 'true' + shell: bash + id: dummy-files + working-directory: ${{ inputs.builddir }} + run: | + : Create dummy files in build dir + set {{a..z},{A..Z},{0..9},foo,bar,test,zzz}.rb + for file; do \ + echo > $file "raise 'do not load $file'"; \ + done + # drop {a..z}.rb if case-insensitive filesystem + grep -F A.rb a.rb > /dev/null && set "${@:27}" + echo clean="cd ${{ inputs.builddir }} && rm $*" >> $GITHUB_OUTPUT + + - if: inputs.clean == 'true' + shell: bash + id: clean + run: | + echo distclean='cd ${{ inputs.builddir }} && ${{ inputs.make-command }} distclean' >> $GITHUB_OUTPUT + echo remained-files='find ${{ inputs.builddir }} -ls' >> $GITHUB_OUTPUT + [ "${{ inputs.builddir }}" = "${{ inputs.srcdir }}" ] || + echo final='rmdir ${{ inputs.builddir }}' >> $GITHUB_OUTPUT + + - name: clean + uses: gacts/run-and-post-run@81b6ce503cde93862cec047c54652e45c5dca991 # v1.4.3 + with: + working-directory: + post: | + ${{ steps.dummy-files.outputs.clean }} + ${{ steps.clean.outputs.distclean }} + ${{ steps.clean.outputs.remained-files }} + ${{ steps.clean.outputs.final }} + # rmdir randomly fails due to launchable files + continue-on-error: true diff --git a/.github/actions/setup/macos/action.yml b/.github/actions/setup/macos/action.yml new file mode 100644 index 0000000000..d0072ff828 --- /dev/null +++ b/.github/actions/setup/macos/action.yml @@ -0,0 +1,29 @@ +name: Setup macOS environment +description: >- + Installs necessary packages via Homebrew. + +inputs: {} # nothing? + +outputs: {} # nothing? + +runs: + using: composite + + steps: + - name: brew + shell: bash + run: | + brew install --quiet jemalloc gmp libffi openssl@3 zlib autoconf automake libtool + + - name: Set ENV + shell: bash + run: | + dir_config() { + local args=() lib var="$1"; shift + for lib in "$@"; do + args+=("--with-${lib%@*}-dir=$(brew --prefix $lib)") + done + echo "$var=${args[*]}" >> $GITHUB_ENV + } + dir_config ruby_configure_args gmp + dir_config CONFIGURE_ARGS openssl@3 diff --git a/.github/actions/setup/ubuntu/action.yml b/.github/actions/setup/ubuntu/action.yml new file mode 100644 index 0000000000..a9e5b41951 --- /dev/null +++ b/.github/actions/setup/ubuntu/action.yml @@ -0,0 +1,53 @@ +name: Setup ubuntu environment +description: >- + At the beginning there was no way but to copy & paste `apt-get` + everywhere. But now that we have composite actions, it seems better + merge them into one. + +inputs: + arch: + required: false + default: '' + description: >- + Architecture. Because we run this on a GitHub-hosted runner + acceptable value for this input is very limited. + +outputs: + arch: + value: ${{ steps.uname.outputs.uname }} + description: >- + Actual architecture. This could be different from the one + passed to the `inputs.arch`. For instance giving `i386` to this + action yields `i686`. + +runs: + using: composite + + steps: + - name: set SETARCH + shell: bash + run: echo "SETARCH=${setarch}" >> "$GITHUB_ENV" + env: + setarch: ${{ inputs.arch && format('setarch {0} --', inputs.arch) }} + + - id: uname + name: uname + shell: bash + run: | + echo uname=`${SETARCH} uname -m` >> "$GITHUB_OUTPUT" + echo dpkg=`${SETARCH} uname -m | sed s/686/386/` >> "$GITHUB_OUTPUT" + + - name: apt-get + shell: bash + env: + arch: ${{ inputs.arch && format(':{0}', steps.uname.outputs.dpkg) || '' }} + run: | + set -x + ${arch:+sudo dpkg --add-architecture ${arch#:}} + sudo apt-get update -qq || : + sudo apt-get install --no-install-recommends -qq -y -o=Dpkg::Use-Pty=0 \ + ${arch:+cross}build-essential${arch/:/-} \ + libssl-dev${arch} libyaml-dev${arch} libreadline6-dev${arch} \ + zlib1g-dev${arch} libncurses5-dev${arch} libffi-dev${arch} \ + autoconf ruby + sudo apt-get install -qq -y pkg-config${arch} || : diff --git a/.github/actions/slack/action.yml b/.github/actions/slack/action.yml new file mode 100644 index 0000000000..4a398da1d1 --- /dev/null +++ b/.github/actions/slack/action.yml @@ -0,0 +1,51 @@ +name: Post a message to slack +description: >- + We have our ruby/action-slack webhook. However its arguments are + bit verbose to be listed in every workflow files. Better merge them + into one. + +inputs: + SLACK_WEBHOOK_URL: + required: true + description: >- + The URL to post the payload. This is an input because it tends + to be stored in a secrets vault and a composite action cannot + look into one. + + label: + required: false + description: >- + Human-readable description of the run, something like "DEBUG=1". + This need not be unique among runs. + + event_name: + required: false + default: 'push' + description: >- + Target event to trigger notification. Notify only push by default. + + extra_channel_id: + required: false + description: >- + Slack channel ID to notify besides #alerts and #alerts-emoji. + +outputs: {} # Nothing? + +runs: + using: composite + + steps: + - uses: ruby/action-slack@54175162371f1f7c8eb94d7c8644ee2479fcd375 # v3.2.2 + with: + payload: | + { + "ci": "GitHub Actions", + "env": "${{ github.workflow }}${{ inputs.label && format(' / {0}', inputs.label) }}", + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "commit": "${{ github.sha }}", + "branch": "${{ github.ref_name }}" + ${{ inputs.extra_channel_id && format(', "extra_channel_id": "{0}"', inputs.extra_channel_id) }} + } + env: + SLACK_WEBHOOK_URL: ${{ inputs.SLACK_WEBHOOK_URL }} + if: ${{ github.event_name == inputs.event_name && startsWith(github.repository, 'ruby/') }} diff --git a/.github/auto_request_review.yml b/.github/auto_request_review.yml new file mode 100644 index 0000000000..38496d5ceb --- /dev/null +++ b/.github/auto_request_review.yml @@ -0,0 +1,20 @@ +files: + 'yjit*': [team:jit] + 'yjit/**/*': [team:jit] + 'yjit/src/cruby_bindings.inc.rs': [] + 'bootstraptest/test_yjit*': [team:jit] + 'test/ruby/test_yjit*': [team:jit] + 'zjit*': [team:jit] + 'zjit/**/*': [team:jit] + 'zjit/src/cruby_bindings.inc.rs': [] + 'test/ruby/test_zjit*': [team:jit] + 'defs/jit.mk': [team:jit] + 'tool/zjit_bisect.rb': [team:jit] + 'doc/jit/*': [team:jit] + # Skip github workflow files because the team don't necessarily need to review dependabot updates for GitHub Actions. It's noisy in notifications, and they're auto-merged anyway. +options: + ignore_draft: true + # This currently doesn't work as intended. We want to skip reviews when only + # cruby_bingings.inc.rs is modified, but this skips reviews even when other + # files are modified as well. To be enabled after fixing the behavior. + #last_files_match_only: true diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml deleted file mode 100644 index 91f82b842b..0000000000 --- a/.github/codeql/codeql-config.yml +++ /dev/null @@ -1,3 +0,0 @@ -name: "CodeQL config for the Ruby language" - -languages: cpp diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..2c2982d1d4 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,22 @@ +version: 2 +updates: + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'daily' + - package-ecosystem: 'github-actions' + directory: '/.github/actions/slack' + schedule: + interval: 'daily' + - package-ecosystem: 'github-actions' + directory: '/.github/actions/setup/directories' + schedule: + interval: 'daily' + - package-ecosystem: 'cargo' + directory: '/yjit' + schedule: + interval: 'daily' + - package-ecosystem: 'vcpkg' + directory: '/' + schedule: + interval: 'daily' diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000000..e81aed8e98 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,6 @@ +Documentation: +- changed-files: + - all-globs-to-all-files: doc/** + +Backport: +- base-branch: 'ruby_3_\d' diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml new file mode 100644 index 0000000000..899d601aef --- /dev/null +++ b/.github/workflows/annocheck.yml @@ -0,0 +1,110 @@ +name: Annocheck + +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + compile: + name: test-annocheck + + runs-on: ubuntu-latest + + container: + image: ghcr.io/ruby/ruby-ci-image:gcc-11 + options: --user root + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + env: + CONFIGURE_TTY: never + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUBY_DEBUG: ci rgengc + RUBY_TESTOPTS: >- + -q + --color=always + --tty=no + # FIXME: Drop skipping options + # https://bugs.ruby-lang.org/issues/18061 + # https://sourceware.org/annobin/annobin.html/Test-pie.html + TEST_ANNOCHECK_OPTS: '--skip-pie --skip-gaps' + + steps: + - run: id + working-directory: + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.1' + bundler: none + + # Minimal flags to pass the check. + # -g0 disables backtraces when SEGV. Do not set that. + - name: Run configure + run: > + ../src/configure -C + --enable-debug-env + --disable-install-doc + --with-ext=-test-/cxxanyargs,+ + --without-valgrind + --without-jemalloc + --without-gmp + --with-gcc="gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes" + --enable-shared + debugflags=-ggdb3 + optflags=-O2 + LDFLAGS=-Wl,-z,now + + - run: make showflags + + - run: make + + - run: make test-annocheck + + - uses: ./.github/actions/slack + with: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/auto_request_review.yml b/.github/workflows/auto_request_review.yml new file mode 100644 index 0000000000..207315a084 --- /dev/null +++ b/.github/workflows/auto_request_review.yml @@ -0,0 +1,20 @@ +name: Auto Request Review +on: + pull_request_target: + types: [opened, ready_for_review, reopened] + branches: [master] + +permissions: + contents: read + +jobs: + auto-request-review: + name: Auto Request Review + runs-on: ubuntu-latest + if: ${{ github.repository == 'ruby/ruby' && github.base_ref == 'master' }} + steps: + - name: Request review based on files changes and/or groups the author belongs to + uses: necojackarc/auto-request-review@e89da1a8cd7c8c16d9de9c6e763290b6b0e3d424 # v0.13.0 + with: + # scope: public_repo + token: ${{ secrets.MATZBOT_AUTO_REQUEST_REVIEW_TOKEN }} diff --git a/.github/workflows/auto_review_pr.yml b/.github/workflows/auto_review_pr.yml new file mode 100644 index 0000000000..ad0e63ba12 --- /dev/null +++ b/.github/workflows/auto_review_pr.yml @@ -0,0 +1,33 @@ +name: Auto Review PR +on: + pull_request_target: + types: [opened, ready_for_review, reopened] + branches: [master] + +permissions: + contents: read + +jobs: + auto-review-pr: + name: Auto Review PR + runs-on: ubuntu-latest + if: ${{ github.repository == 'ruby/ruby' && github.base_ref == 'master' }} + + permissions: + pull-requests: write + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v6.0.1 + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.4' + bundler: none + + - name: Auto Review PR + run: ruby tool/auto_review_pr.rb "$GITHUB_PR_NUMBER" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 788ca8f474..d3e734f885 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -1,46 +1,74 @@ name: BASERUBY Check -on: [push, pull_request] +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read jobs: baseruby: name: BASERUBY - runs-on: ubuntu-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.event.pull_request.user.login == 'dependabot[bot]') + )}} + strategy: matrix: ruby: - - ruby-2.2 -# - ruby-2.3 -# - ruby-2.4 -# - ruby-2.5 -# - ruby-2.6 - - ruby-2.7 - - ruby-3.0 + - ruby-3.1 + - ruby-3.2 + - ruby-3.3 steps: - - uses: actions/checkout@v2 - - uses: ruby/setup-ruby@v1 + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 with: ruby-version: ${{ matrix.ruby }} bundler: none - - run: echo "make=make -sj$((1 + $(nproc --all)))" >> $GITHUB_ENV - - run: sudo apt-get install build-essential autoconf bison - - run: ./autogen.sh + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: ./.github/actions/setup/ubuntu + + - uses: ./.github/actions/setup/directories + with: + makeup: true + - run: ./configure --disable-install-doc - - run: $make common-srcs - - run: $make incs - - run: $make all - - run: $make test - - uses: k0kubun/action-slack@v2.0.0 + + - run: make all + + - run: make test + + - uses: ./.github/actions/slack with: - payload: | - { - "ci": "GitHub Actions", - "env": "${{ github.workflow }} / BASERUBY @ ${{ matrix.ruby }}", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } - env: + label: ${{ matrix.ruby }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml index d46c0704cd..59f64e8312 100644 --- a/.github/workflows/bundled_gems.yml +++ b/.github/workflows/bundled_gems.yml @@ -1,66 +1,190 @@ name: bundled_gems +env: + UPDATE_ENABLED: true + on: + push: + branches: ['master'] + paths: + - '.github/workflows/bundled_gems.yml' + - 'gems/bundled_gems' + pull_request: + branches: ['master'] + paths: + - '.github/workflows/bundled_gems.yml' + - 'gems/bundled_gems' + merge_group: schedule: - cron: '45 6 * * *' + workflow_dispatch: + +permissions: # added using https://github.com/step-security/secure-workflows + contents: read jobs: update: - if: ${{ github.repository == 'ruby/ruby' }} + permissions: + contents: write # for Git to git push + + if: ${{ github.event_name != 'schedule' || github.repository == 'ruby/ruby' }} + name: update ${{ github.workflow }} + runs-on: ubuntu-latest + steps: - - name: git config - run: | - git config --global advice.detachedHead 0 - git config --global init.defaultBranch garbage + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} + + - uses: ./.github/actions/setup/directories + with: + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN + checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) - name: Set ENV run: | - echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV + echo "TODAY=$(date +%F)" >> $GITHUB_ENV - - uses: actions/checkout@v2 + - name: Download previous gems list + run: | + mkdir -p .downloaded-cache + for data in bundled_gems.json default_gems.json; do + ln -s .downloaded-cache/$data . + curl -O -R -z ./$data https://stdgems.org/$data + done - - name: Update ${{ github.workflow }} + - name: Update bundled gems list + id: bundled_gems run: | - ruby -i~ tool/update-bundled_gems.rb gems/${{ github.workflow }} + ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems >> $GITHUB_OUTPUT + if: ${{ env.UPDATE_ENABLED == 'true' }} + + - name: Update spec/bundler/support/builders.rb + run: | + #!ruby + rake_version = File.read("gems/bundled_gems")[/^rake\s+(\S+)/, 1] + print ARGF.read.sub(/^ *def rake_version\s*\K".*?"/) {rake_version.dump} + shell: ruby -i~ {0} spec/bundler/support/builders.rb + if: ${{ env.UPDATE_ENABLED == 'true' }} + + - name: Maintain updated gems list in NEWS + run: | + ruby tool/update-NEWS-gemlist.rb bundled + if: ${{ env.UPDATE_ENABLED == 'true' }} - name: Check diffs id: diff run: | - git diff --no-ext-diff --ignore-submodules --exit-code - continue-on-error: true + news= gems= + git diff --color --no-ext-diff --ignore-submodules --exit-code -- NEWS.md || + news=true + git diff --color --no-ext-diff --ignore-submodules --exit-code -- gems/bundled_gems || + gems=true + git add -- NEWS.md gems/bundled_gems + git add -- spec/bundler/support/builders.rb + echo news=$news >> $GITHUB_OUTPUT + echo gems=$gems >> $GITHUB_OUTPUT + echo update=${news:-$gems} >> $GITHUB_OUTPUT - - name: Install libraries + - name: Commit + id: commit run: | - set -x - sudo apt-get update -q || : - sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby - if: ${{ steps.diff.outcome == 'failure' }} + git pull --ff-only origin ${GITHUB_REF#refs/heads/} + message="Update bundled gems list" + if [ -z "${gems}" ]; then + git commit --message="[DOC] ${message} at ${GITHUB_SHA:0:30}" + else + git commit --message="${message} as of ${TODAY}" + fi + env: + TODAY: ${{ steps.bundled_gems.outputs.latest_date || env.TODAY }} + EMAIL: svn-admin@ruby-lang.org + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + gems: ${{ steps.diff.outputs.gems }} + if: ${{ steps.diff.outputs.update }} + + - name: Development revision of bundled gems + run: | + #!ruby + file = "gems/bundled_gems" + + SECONDS_IN_DAY = 86400 + today = Time.new("#{ENV['TODAY']}Z") + if !(december = today.month == 12) + days = 30 + elsif (days = 26 - today.day).positive? + days += 4 + else + puts "::info:: just after released" + exit + end + + since = "#{today.year-1}-12-26" + ref = ENV['GITHUB_REF'] + puts "::group::\e[94mfetching \e[1m#{file}\e[22m since \e[1m#{since}\e[22m from \e[1m#{ref}\e[m" + system(*%W[git fetch --shallow-since=#{since} --no-tags origin #{ref}], exception: true) + puts "::endgroup::" + + puts "\e[94mchecking development version bundled gems older than \e[1m#{days}\e[22m days\e[m" + limit = today.to_i - days * SECONDS_IN_DAY + old = 0 + IO.popen(%W"git blame --line-porcelain -- #{file}") do |blame| + while head = blame.gets("\n\t") and s = blame.gets + next unless (gem = s.split(/\s+|#.*/)).size > 3 + time = head[/^committer-time \K\d+/].to_i + next if (d = limit - time) <= 0 + d /= SECONDS_IN_DAY + line = head[/\A\h+ \d+ \K\d+/].to_i + level = if d < days; 'warning'; else old += 1; 'error'; end + d += days + puts "::#{level} file=#{file},line=#{line},title=Older than #{d} days::#{gem[0]} #{gem[3]}" + end + end + abort "::error title=Too long-standing gems::The release comes soon." if december and old.nonzero? + shell: ruby {0} + env: + file: ${{ steps.logs.outputs.file }} + days: ${{ steps.logs.outputs.days }} + + - name: Install libraries + uses: ./.github/actions/setup/ubuntu + if: ${{ steps.diff.outputs.gems }} - name: Build run: | ./autogen.sh ./configure -C --disable-install-doc - make $JOBS - if: ${{ steps.diff.outcome == 'failure' }} + make + if: ${{ steps.diff.outputs.gems }} + + - name: Prepare bundled gems + run: | + make -s prepare-gems + if: ${{ steps.diff.outputs.gems }} - name: Test bundled gems run: | - make $JOBS -s test-bundled-gems + make -s test-bundled-gems timeout-minutes: 30 env: - RUBY_TESTOPTS: "-q --tty=no" - TEST_BUNDLED_GEMS_ALLOW_FAILURES: "" - if: ${{ steps.diff.outcome == 'failure' }} + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + if: ${{ steps.diff.outputs.gems }} - - name: Commit + - name: Push run: | - git commit --message="Update ${{ github.workflow }} at $(date +%F)" gems/${{ github.workflow }} - git pull --ff-only origin ${GITHUB_REF#refs/heads/} git push origin ${GITHUB_REF#refs/heads/} - env: - EMAIL: svn-admin@ruby-lang.org - GIT_AUTHOR_NAME: git - GIT_COMMITTER_NAME: git - if: ${{ steps.diff.outcome == 'failure' }} + if: >- + ${{ + github.repository == 'ruby/ruby' && + !startsWith(github.event_name, 'pull') && + steps.commit.outcome == 'success' + }} + + - uses: ./.github/actions/slack + with: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index e6b4abbe98..c5dec65e48 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -1,45 +1,59 @@ name: Check Dependencies -on: [push, pull_request] +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + jobs: update-deps: + name: Dependency checks + strategy: matrix: - os: [ubuntu-20.04, macos-11] + os: [ubuntu-latest] fail-fast: true + runs-on: ${{ matrix.os }} + steps: - - 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 libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: ./.github/actions/setup/ubuntu if: ${{ contains(matrix.os, 'ubuntu') }} - - name: Install libraries - run: | - brew upgrade - brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline + + - uses: ./.github/actions/setup/macos if: ${{ contains(matrix.os, 'macos') }} - - name: git config - run: | - git config --global advice.detachedHead 0 - git config --global init.defaultBranch garbage - - uses: actions/checkout@v2 - - run: ./autogen.sh + + - uses: ./.github/actions/setup/directories + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.1' + bundler: none + - name: Run configure run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g' - - run: make all golf - - run: ruby tool/update-deps --fix + + - run: make fix-depends + - run: git diff --no-ext-diff --ignore-submodules --exit-code - - uses: k0kubun/action-slack@v2.0.0 + + - uses: ./.github/actions/slack with: - payload: | - { - "ci": "GitHub Actions", - "env": "${{ matrix.os }} / Dependencies need to update", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } - env: + label: ${{ matrix.os }} / Dependencies need to update SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml index c116011d86..2a2bd1df53 100644 --- a/.github/workflows/check_misc.yml +++ b/.github/workflows/check_misc.yml @@ -1,20 +1,127 @@ -name: Miscellaneous checks -on: [push, pull_request] +name: Misc +on: [push, pull_request, merge_group] + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read jobs: checks: + name: Miscellaneous checks + + permissions: + contents: write # for Git to git push + runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v2 - - name: Check if C-sources are US-ASCII + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} + + - uses: ./.github/actions/setup/directories + with: + makeup: true + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN + checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) + + - name: Check for code styles run: | - ! grep -r -n '[^ -~]' *.[chy] include internal win32/*.[ch] - - name: Check for trailing spaces + set -x + ruby tool/auto-style.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" + env: + GITHUB_OLD_SHA: ${{ github.event.pull_request.base.sha }} + GITHUB_NEW_SHA: ${{ github.event.pull_request.merge_commit_sha }} + # Skip 'push' events because post_push.yml fixes them on push + if: ${{ github.repository == 'ruby/ruby' && startsWith(github.event_name, 'pull') }} + + - name: Check for bash specific substitution in configure.ac run: | - ! git grep -n '[ ]$' '*.rb' '*.[chy]' + git grep -n '\${[A-Za-z_0-9]*/' -- configure.ac && exit 1 || : + - name: Check for header macros run: | - ! for header in ruby/*.h; do \ - git grep -l -F -e $header -e HAVE_`echo $header | tr a-z./ A-Z__` -- . > /dev/null || echo $header - done | grep -F . + fail= + for header in ruby/*.h; do + git grep -l -F -e $header -e HAVE_`echo $header | tr a-z./ A-Z__` -- . > /dev/null && continue + fail=1 + echo $header + done + exit $fail working-directory: include + + - id: now + run: | + date +"mon=%-m"%n"day=%-d" >> $GITHUB_OUTPUT + env: + TZ: Tokyo/Asia + + - id: deprecation + run: | + eval $(sed -n 's/^#define RUBY_API_VERSION_\(MAJOR\|MINOR\) /\1=/p' include/ruby/version.h) + if git --no-pager grep --color -o 'rb_warn_deprecated_to_remove_at('$MAJOR'\.'$MINOR',.*' -- '*.c' >&2; then + false + else + true + fi + continue-on-error: ${{ steps.now.outputs.mon < 12 }} + + - name: Check if to generate documents + id: rdoc + run: | + set -- $(sed 's/#.*//;/^rdoc /!d' gems/bundled_gems) + { echo version=$2; echo ref=$4; } >> $GITHUB_OUTPUT + echo RDOC='ruby -W0 --disable-gems tool/rdoc-srcdir -q' >> $GITHUB_ENV + + - name: Checkout rdoc + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + repository: ruby/rdoc + ref: ${{ steps.rdoc.outputs.ref }} + path: .bundle/gems/rdoc-${{ steps.rdoc.outputs.version }} + if: ${{ steps.rdoc.outputs.ref != '' }} + + - name: Generate rdoc + run: | + set -x + gempath=$(ruby -e 'print Gem.user_dir, "/bin"') + PATH=$gempath:$PATH + gem install --user bundler + bundle config --local path vendor/bundle + bundle install --jobs 4 + bundle exec rake generate + working-directory: .bundle/gems/rdoc-${{ steps.rdoc.outputs.version }} + if: ${{ steps.rdoc.outputs.ref != '' }} + + - name: Core docs coverage + run: | + $RDOC -C -x ^ext -x ^lib . + + - name: Generate docs + id: docs + run: | + $RDOC --op html . + echo htmlout=ruby-html-${GITHUB_SHA:0:10} >> $GITHUB_OUTPUT + # Generate only when document commit/PR + if: >- + ${{false + || contains(github.event.head_commit.message, '[ruby/rdoc]') + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + }} + + - name: Upload docs + uses: actions/upload-artifact@v6.0.0 + with: + path: html + name: ${{ steps.docs.outputs.htmlout }} + if: ${{ steps.docs.outcome == 'success' }} + + - uses: ./.github/actions/slack + with: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 19ad77d393..a92c93b476 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,37 +1,121 @@ -name: "Code scanning - action" +name: 'CodeQL' on: push: + branches: ['master'] + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' schedule: - - cron: '0 12 * * 4' + - cron: '0 12 * * *' + workflow_dispatch: -jobs: - CodeQL-Build: +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: # added using https://github.com/step-security/secure-workflows + contents: read - # CodeQL runs on ubuntu-latest and windows-latest +jobs: + analyze: + name: Analyze runs-on: ubuntu-latest + permissions: + actions: read # for github/codeql-action/init to get workflow details + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/autobuild to send a status report + # CodeQL fails to run pull requests from dependabot due to missing write access to upload results. + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + env: + enable_install_doc: no + + strategy: + fail-fast: false + matrix: + include: + - language: cpp + - language: ruby steps: - - name: 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 libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby + - name: Checkout repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Install libraries + if: ${{ contains(matrix.os, 'macos') }} + uses: ./.github/actions/setup/macos + + - name: Install libraries + if : ${{ matrix.os == 'ubuntu-latest' }} + uses: ./.github/actions/setup/ubuntu + + - uses: ./.github/actions/setup/directories + + - name: Remove an obsolete rubygems vendored file + if: ${{ matrix.os == 'ubuntu-latest' }} + run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb - - name: Checkout repository - uses: actions/checkout@v2 + - name: Initialize CodeQL + uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + with: + languages: ${{ matrix.language }} + trap-caching: false + debug: true - - name: Remove an obsolete rubygems vendored file - run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb + - name: Autobuild + uses: github/codeql-action/autobuild@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - config-file: ./.github/codeql/codeql-config.yml + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + with: + category: '/language:${{ matrix.language }}' + upload: False + output: sarif-results - - name: Autobuild - uses: github/codeql-action/autobuild@v1 + - name: filter-sarif + uses: advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d # v1.0.1 + with: + patterns: | + +**/*.rb + -lib/uri/mailto.rb:rb/overly-large-range + -lib/uri/rfc3986_parser.rb:rb/overly-large-range + -lib/bundler/vendor/uri/lib/uri/mailto.rb:rb/overly-large-range + -lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb:rb/overly-large-range + -test/ruby/test_io.rb:rb/non-constant-kernel-open + -test/open-uri/test_open-uri.rb:rb/non-constant-kernel-open + -test/open-uri/test_ssl.rb:rb/non-constant-kernel-open + -spec/ruby/core/io/binread_spec.rb:rb/non-constant-kernel-open + -spec/ruby/core/io/readlines_spec.rb:rb/non-constant-kernel-open + -spec/ruby/core/io/foreach_spec.rb:rb/non-constant-kernel-open + -spec/ruby/core/io/write_spec.rb:rb/non-constant-kernel-open + -spec/ruby/core/io/read_spec.rb:rb/non-constant-kernel-open + -spec/ruby/core/kernel/open_spec.rb:rb/non-constant-kernel-open + input: sarif-results/${{ matrix.language }}.sarif + output: sarif-results/${{ matrix.language }}.sarif + if: ${{ matrix.language == 'ruby' }} + continue-on-error: true - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + with: + sarif_file: sarif-results/${{ matrix.language }}.sarif + continue-on-error: true diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml index 6ddfba05db..8c0ca54e0b 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -1,226 +1,334 @@ +# Some tests depending on this name 'Compilations' via $GITHUB_WORKFLOW. Make sure to update such tests when renaming this workflow. name: Compilations -on: [push, pull_request] - -# 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-14 - append_cc: '' - crosshost: '' - - # -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 - - UPDATE_UNICODE: >- - UNICODE_FILES=. - UNICODE_PROPERTY_FILES=. - UNICODE_AUXILIARY_FILES=. - UNICODE_EMOJI_FILES=. - CONFIGURE_TTY: never - GITPULLOPTIONS: --no-tags origin ${{github.ref}} - RUBY_DEBUG: ci rgengc - RUBY_TESTOPTS: >- - -q - --color=always - --tty=no +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +# Each job is split so that they roughly take 30min to run through. jobs: - compile: - strategy: - fail-fast: false - matrix: - entry: - - { key: default_cc, name: gcc-11, value: gcc-11, container: gcc-11 } - - { key: default_cc, name: gcc-10, value: gcc-10, container: gcc-10 } - - { key: default_cc, name: gcc-9, value: gcc-9, container: gcc-9 } - - { key: default_cc, name: gcc-8, value: gcc-8, container: gcc-8 } - - { key: default_cc, name: gcc-7, value: gcc-7, container: gcc-7 } - - { key: default_cc, name: gcc-6, value: gcc-6, container: gcc-6 } - - { key: default_cc, name: gcc-5, value: gcc-5, container: gcc-5 } - - { key: default_cc, name: gcc-4.8, value: gcc-4.8, container: gcc-4.8 } - - key: default_cc - name: 'gcc-11 LTO' - value: 'gcc-11 -O2 -flto=auto -ffat-lto-objects' - container: gcc-11 - shared: '--disable-shared' - # check: true - - { key: default_cc, name: clang-14, value: clang-14, container: clang-14 } - - { key: default_cc, name: clang-13, value: clang-13, container: clang-13 } - - { key: default_cc, name: clang-12, value: clang-12, container: clang-12 } - - { key: default_cc, name: clang-11, value: clang-11, container: clang-11 } - - { key: default_cc, name: clang-10, value: clang-10, container: clang-10 } - - { key: default_cc, name: clang-9, value: clang-9, container: clang-9 } - - { key: default_cc, name: clang-8, value: clang-8, container: clang-8 } - - { key: default_cc, name: clang-7, value: clang-7, container: clang-7 } - - { key: default_cc, name: clang-6.0, value: clang-6.0, container: clang-6.0 } - - { key: default_cc, name: clang-5.0, value: clang-5.0, container: clang-5.0 } - - { key: default_cc, name: clang-4.0, value: clang-4.0, container: clang-4.0 } - - { key: default_cc, name: clang-3.9, value: clang-3.9, container: clang-3.9 } - - key: default_cc - name: 'clang-14 LTO' - value: 'clang-14 -O2 -flto=auto' - container: clang-14 - shared: '--disable-shared' - # check: true - - - { key: crosshost, name: aarch64-linux-gnu, value: aarch64-linux-gnu, container: crossbuild-essential-arm64 } -# - { key: crosshost, name: arm-linux-gnueabi, value: arm-linux-gnueabi } -# - { key: crosshost, name: arm-linux-gnueabihf, value: arm-linux-gnueabihf } -# - { key: crosshost, name: i686-w64-mingw32, value: i686-w64-mingw32 } -# - { key: crosshost, name: powerpc-linux-gnu, value: powerpc-linux-gnu } - - { key: crosshost, name: powerpc64le-linux-gnu, value: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el } - - { key: crosshost, name: s390x-linux-gnu, value: s390x-linux-gnu, container: crossbuild-essential-s390x } - - { key: crosshost, name: x86_64-w64-mingw32, value: x86_64-w64-mingw32, container: mingw-w64 } - - - { key: append_cc, name: c99, value: '-std=c99 -Werror=pedantic -pedantic-errors' } -# - { key: append_cc, name: c11, value: '-std=c11 -Werror=pedantic -pedantic-errors' } -# - { key: append_cc, name: c17, value: '-std=c17 -Werror=pedantic -pedantic-errors' } - - { key: append_cc, name: c2x, value: '-std=c2x -Werror=pedantic -pedantic-errors' } - - { key: CXXFLAGS, name: c++98, value: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } -# - { key: CXXFLAGS, name: c++11, value: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } -# - { key: CXXFLAGS, name: c++14, value: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } -# - { key: CXXFLAGS, name: c++17, value: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } - - { key: CXXFLAGS, name: c++2a, value: '-std=c++2a -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } - - - { key: optflags, name: '-O0', value: '-O0 -march=x86-64 -mtune=generic' } -# - { key: optflags, name: '-O3', value: '-O3 -march=x86-64 -mtune=generic', check: true } - - - { key: append_configure, name: gmp, value: '--with-gmp' } - - { key: append_configure, name: jemalloc, value: '--with-jemalloc' } - - { key: append_configure, name: valgrind, value: '--with-valgrind' } - - { key: append_configure, name: 'coroutine=ucontext', value: '--with-coroutine=ucontext' } - - { key: append_configure, name: 'coroutine=pthread', value: '--with-coroutine=pthread' } - - { key: append_configure, name: disable-jit-support, value: '--disable-jit-support' } - - { key: append_configure, name: disable-dln, value: '--disable-dln' } - - { key: append_configure, name: disable-rubygems, value: '--disable-rubygems' } - - - { key: cppflags, name: OPT_THREADED_CODE=1, value: '-DOPT_THREADED_CODE=1' } - - { key: cppflags, name: OPT_THREADED_CODE=2, value: '-DOPT_THREADED_CODE=2' } - - { key: cppflags, name: OPT_THREADED_CODE=3, value: '-DOPT_THREADED_CODE=3' } - - - { key: cppflags, name: NDEBUG, value: '-DNDEBUG' } - - { key: cppflags, name: RUBY_DEBUG, value: '-DRUBY_DEBUG' } -# - { key: cppflags, name: ARRAY_DEBUG, value: '-DARRAY_DEBUG' } -# - { key: cppflags, name: BIGNUM_DEBUG, value: '-DBIGNUM_DEBUG' } -# - { key: cppflags, name: CCAN_LIST_DEBUG, value: '-DCCAN_LIST_DEBUG' } -# - { key: cppflags, name: CPDEBUG=-1, value: '-DCPDEBUG=-1' } -# - { key: cppflags, name: ENC_DEBUG, value: '-DENC_DEBUG' } -# - { key: cppflags, name: GC_DEBUG, value: '-DGC_DEBUG' } -# - { key: cppflags, name: HASH_DEBUG, value: '-DHASH_DEBUG' } -# - { key: cppflags, name: ID_TABLE_DEBUG, value: '-DID_TABLE_DEBUG' } -# - { key: cppflags, name: RGENGC_DEBUG=-1, value: '-DRGENGC_DEBUG=-1' } -# - { key: cppflags, name: SYMBOL_DEBUG, value: '-DSYMBOL_DEBUG' } -# - { key: cppflags, name: THREAD_DEBUG=-1, value: '-DTHREAD_DEBUG=-1' } - -# - { key: cppflags, name: RGENGC_CHECK_MODE, value: '-DRGENGC_CHECK_MODE' } -# - { key: cppflags, name: TRANSIENT_HEAP_CHECK_MODE, value: '-DTRANSIENT_HEAP_CHECK_MODE' } -# - { key: cppflags, name: VM_CHECK_MODE, value: '-DVM_CHECK_MODE' } - - - { key: cppflags, name: USE_EMBED_CI=0, value: '-DUSE_EMBED_CI=0' } - - { key: cppflags, name: USE_FLONUM=0, value: '-DUSE_FLONUM=0' } -# - { key: cppflags, name: USE_GC_MALLOC_OBJ_INFO_DETAILS, value: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' } - - { key: cppflags, name: USE_LAZY_LOAD, value: '-DUSE_LAZY_LOAD' } -# - { key: cppflags, name: USE_RINCGC=0, value: '-DUSE_RINCGC=0' } -# - { key: cppflags, name: USE_SYMBOL_GC=0, value: '-DUSE_SYMBOL_GC=0' } -# - { key: cppflags, name: USE_THREAD_CACHE=0, value: '-DUSE_THREAD_CACHE=0' } -# - { key: cppflags, name: USE_TRANSIENT_HEAP=0, value: '-DUSE_TRANSIENT_HEAP=0' } -# - { key: cppflags, name: USE_RUBY_DEBUG_LOG=1, value: '-DUSE_RUBY_DEBUG_LOG=1' } - - - { key: cppflags, name: DEBUG_FIND_TIME_NUMGUESS, value: '-DDEBUG_FIND_TIME_NUMGUESS' } - - { key: cppflags, name: DEBUG_INTEGER_PACK, value: '-DDEBUG_INTEGER_PACK' } -# - { key: cppflags, name: ENABLE_PATH_CHECK, value: '-DENABLE_PATH_CHECK' } - - - { key: cppflags, name: GC_DEBUG_STRESS_TO_CLASS, value: '-DGC_DEBUG_STRESS_TO_CLASS' } -# - { key: cppflags, name: GC_ENABLE_LAZY_SWEEP=0, value: '-DGC_ENABLE_LAZY_SWEEP=0' } -# - { key: cppflags, name: GC_PROFILE_DETAIL_MEMOTY, value: '-DGC_PROFILE_DETAIL_MEMOTY' } -# - { key: cppflags, name: GC_PROFILE_MORE_DETAIL, value: '-DGC_PROFILE_MORE_DETAIL' } - -# - { key: cppflags, name: CALC_EXACT_MALLOC_SIZE, value: '-DCALC_EXACT_MALLOC_SIZE' } -# - { key: cppflags, name: MALLOC_ALLOCATED_SIZE_CHECK, value: '-DMALLOC_ALLOCATED_SIZE_CHECK' } - -# - { key: cppflags, name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, value: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' } - -# - { key: cppflags, name: RGENGC_ESTIMATE_OLDMALLOC, value: '-DRGENGC_ESTIMATE_OLDMALLOC' } -# - { key: cppflags, name: RGENGC_FORCE_MAJOR_GC, value: '-DRGENGC_FORCE_MAJOR_GC' } -# - { key: cppflags, name: RGENGC_OBJ_INFO, value: '-DRGENGC_OBJ_INFO' } -# - { key: cppflags, name: RGENGC_OLD_NEWOBJ_CHECK, value: '-DRGENGC_OLD_NEWOBJ_CHECK' } -# - { key: cppflags, name: RGENGC_PROFILE, value: '-DRGENGC_PROFILE' } - -# - { key: cppflags, name: VM_DEBUG_BP_CHECK, value: '-DVM_DEBUG_BP_CHECK' } -# - { key: cppflags, name: VM_DEBUG_VERIFY_METHOD_CACHE, value: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } - - - { key: cppflags, name: MJIT_FORCE_ENABLE, value: '-DMJIT_FORCE_ENABLE' } - - 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 || 'clang-14' }} - options: --user root + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} steps: - - run: id - working-directory: - - run: mkdir build + - run: true working-directory: - - name: setenv - run: | - echo "${{ matrix.entry.key }}=${{ matrix.entry.value }}" >> $GITHUB_ENV - echo "GNUMAKEFLAGS=-sj$((1 + $(nproc --all)))" >> $GITHUB_ENV - - uses: actions/checkout@v2 + + compile1: + name: 'omnibus compilations, #1' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + # Set fetch-depth: 10 so that Launchable can receive commits information. + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - name: 'clang 18 LTO' + uses: './.github/actions/compilers' with: - path: src - - run: ./autogen.sh - working-directory: src - - name: Run configure - run: > - ../src/configure -C ${default_configure} ${append_configure} - ${{ matrix.entry.key == 'crosshost' && '--host="${crosshost}"' || '--with-gcc="${default_cc} ${append_cc}"' }} - ${{ matrix.entry.shared || '--enable-shared' }} - - run: make extract-extlibs - - run: make incs - - run: make - - run: make leaked-globals - - run: make test - - run: make install - if: ${{ matrix.entry.check }} - - run: /usr/local/bin/gem install --no-doc timezone tzinfo - if: ${{ matrix.entry.check }} - - run: make test-tool - if: ${{ matrix.entry.check }} - - run: make test-all TESTS='-- ruby -ext-' - if: ${{ matrix.entry.check }} - - run: make test-spec - if: ${{ matrix.entry.check }} - - - uses: k0kubun/action-slack@v2.0.0 + tag: clang-18 + with_gcc: 'clang-18 -flto=auto' + optflags: '-O2' + enable_shared: false + timeout-minutes: 30 + - { uses: './.github/actions/compilers', name: '-O0', with: { optflags: '-O0 -march=x86-64 -mtune=generic' }, timeout-minutes: 5 } + # - { uses: './.github/actions/compilers', name: '-O3', with: { optflags: '-O3 -march=x86-64 -mtune=generic', check: true } } + + compile2: + name: 'omnibus compilations, #2' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - name: 'GCC 15 LTO' + uses: './.github/actions/compilers' + with: + tag: gcc-15 + with_gcc: 'gcc-15 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch' + optflags: '-O2' + enable_shared: false + timeout-minutes: 10 + - { uses: './.github/actions/compilers', name: 'ext/Setup', with: { static_exts: 'etc json/* */escape' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 15', with: { tag: 'gcc-15' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 14', with: { tag: 'gcc-14' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 13', with: { tag: 'gcc-13' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 12', with: { tag: 'gcc-12' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 11', with: { tag: 'gcc-11' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 10', with: { tag: 'gcc-10' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 9', with: { tag: 'gcc-9' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 8', with: { tag: 'gcc-8' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GCC 7', with: { tag: 'gcc-7' }, timeout-minutes: 5 } + + compile3: + name: 'omnibus compilations, #3' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'clang 22', with: { tag: 'clang-22' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 21', with: { tag: 'clang-21' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 20', with: { tag: 'clang-20' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 19', with: { tag: 'clang-19' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 18', with: { tag: 'clang-18' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 17', with: { tag: 'clang-17' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 16', with: { tag: 'clang-16' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 15', with: { tag: 'clang-15' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 14', with: { tag: 'clang-14' }, timeout-minutes: 5 } + + compile4: + name: 'omnibus compilations, #4' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'clang 13', with: { tag: 'clang-13' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 12', with: { tag: 'clang-12' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 11', with: { tag: 'clang-11' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 10', with: { tag: 'clang-10' }, timeout-minutes: 5 } + # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o and fail `make test-leaked-globals`. + - { uses: './.github/actions/compilers', name: 'clang 9', with: { tag: 'clang-9', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 8', with: { tag: 'clang-8', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 7', with: { tag: 'clang-7', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'clang 6', with: { tag: 'clang-6.0', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 } + + compile5: + name: 'omnibus compilations, #5' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + # -Wno-strict-prototypes is necessary with current clang-15 since + # older autoconf generate functions without prototype and -pedantic + # now implies strict-prototypes. Disabling the error but leaving the + # warning generates a lot of noise from use of ANYARGS in + # rb_define_method() and friends. + # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94 + - { uses: './.github/actions/compilers', name: 'C99', with: { CFLAGS: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C11', with: { CFLAGS: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C17', with: { CFLAGS: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C23', with: { CFLAGS: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C++98', with: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C++11', with: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C++14', with: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C++17', with: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 } + + compile6: + name: 'omnibus compilations, #6' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'C++20', with: { CXXFLAGS: '-std=c++20 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C++23', with: { CXXFLAGS: '-std=c++23 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'C++26', with: { CXXFLAGS: '-std=c++26 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'gmp', with: { append_configure: '--with-gmp', test_all: 'ruby/test_bignum.rb', test_spec: "/github/workspace/src/spec/ruby/core/integer" }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'jemalloc', with: { append_configure: '--with-jemalloc' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'valgrind', with: { append_configure: '--with-valgrind' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'coroutine=ucontext', with: { append_configure: '--with-coroutine=ucontext' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'coroutine=pthread', with: { append_configure: '--with-coroutine=pthread' }, timeout-minutes: 5 } + + compile7: + name: 'omnibus compilations, #7' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'disable-jit', with: { append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'disable-yjit', with: { append_configure: '--disable-yjit' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'disable-zjit', with: { append_configure: '--disable-zjit' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'disable-dln', with: { append_configure: '--disable-dln' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'enable-mkmf-verbose', with: { append_configure: '--enable-mkmf-verbose' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'disable-rubygems', with: { append_configure: '--disable-rubygems' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'RUBY_DEVEL', with: { append_configure: '--enable-devel' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=0', with: { cppflags: '-DOPT_THREADED_CODE=0' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=1', with: { cppflags: '-DOPT_THREADED_CODE=1' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=2', with: { cppflags: '-DOPT_THREADED_CODE=2' }, timeout-minutes: 5 } + + compile8: + name: 'omnibus compilations, #8' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'NDEBUG', with: { cppflags: '-DNDEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'RUBY_DEBUG', with: { cppflags: '-DRUBY_DEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'ARRAY_DEBUG', with: { cppflags: '-DARRAY_DEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'BIGNUM_DEBUG', with: { cppflags: '-DBIGNUM_DEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'CCAN_LIST_DEBUG', with: { cppflags: '-DCCAN_LIST_DEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'CPDEBUG=-1', with: { cppflags: '-DCPDEBUG=-1' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'ENC_DEBUG', with: { cppflags: '-DENC_DEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GC_DEBUG', with: { cppflags: '-DGC_DEBUG' }, timeout-minutes: 5 } + + compile9: + name: 'omnibus compilations, #9' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'HASH_DEBUG', with: { cppflags: '-DHASH_DEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'ID_TABLE_DEBUG', with: { cppflags: '-DID_TABLE_DEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'RGENGC_DEBUG=-1', with: { cppflags: '-DRGENGC_DEBUG=-1' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'SYMBOL_DEBUG', with: { cppflags: '-DSYMBOL_DEBUG' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'RGENGC_CHECK_MODE', with: { cppflags: '-DRGENGC_CHECK_MODE' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'VM_CHECK_MODE', with: { cppflags: '-DVM_CHECK_MODE' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'USE_EMBED_CI=0', with: { cppflags: '-DUSE_EMBED_CI=0' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'USE_FLONUM=0', with: { cppflags: '-DUSE_FLONUM=0', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 } + + compileX: + name: 'omnibus compilations, #10' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'USE_LAZY_LOAD', with: { cppflags: '-DUSE_LAZY_LOAD' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'USE_SYMBOL_GC=0', with: { cppflags: '-DUSE_SYMBOL_GC=0' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'USE_THREAD_CACHE=0', with: { cppflags: '-DUSE_THREAD_CACHE=0' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'USE_RUBY_DEBUG_LOG=1', with: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'USE_DEBUG_COUNTER', with: { cppflags: '-DUSE_DEBUG_COUNTER=1' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'SHARABLE_MIDDLE_SUBSTRING', with: { cppflags: '-DSHARABLE_MIDDLE_SUBSTRING=1' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'DEBUG_FIND_TIME_NUMGUESS', with: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'DEBUG_INTEGER_PACK', with: { cppflags: '-DDEBUG_INTEGER_PACK' }, timeout-minutes: 5 } + + compileB: + name: 'omnibus compilations, #11' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'GC_DEBUG_STRESS_TO_CLASS', with: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GC_ENABLE_LAZY_SWEEP=0', with: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GC_PROFILE_DETAIL_MEMORY', with: { cppflags: '-DGC_PROFILE_DETAIL_MEMORY' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'GC_PROFILE_MORE_DETAIL', with: { cppflags: '-DGC_PROFILE_MORE_DETAIL' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'MALLOC_ALLOCATED_SIZE_CHECK', with: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'RGENGC_ESTIMATE_OLDMALLOC', with: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'RGENGC_PROFILE', with: { cppflags: '-DRGENGC_PROFILE' }, timeout-minutes: 5 } + + compileC: + name: 'omnibus compilations, #12' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'VM_DEBUG_BP_CHECK', with: { cppflags: '-DVM_DEBUG_BP_CHECK' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'VM_DEBUG_VERIFY_METHOD_CACHE', with: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'YJIT_FORCE_ENABLE', with: { cppflags: '-DYJIT_FORCE_ENABLE' }, timeout-minutes: 5 } + - { uses: './.github/actions/compilers', name: 'UNIVERSAL_PARSER', with: { cppflags: '-DUNIVERSAL_PARSER' }, timeout-minutes: 5 } + + compilemax: + name: 'omnibus compilations, result' + runs-on: ubuntu-latest + if: ${{ always() }} + needs: + - 'compile1' + - 'compile2' + - 'compile3' + - 'compile4' + - 'compile5' + - 'compile6' + - 'compile7' + - 'compile8' + - 'compile9' + - 'compileX' + - 'compileB' + - 'compileC' + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - uses: ./.github/actions/slack with: - payload: | - { - "ci": "GitHub Actions", - "env": "${{ github.workflow }} / ${{ matrix.entry.name }}", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } - env: + label: 'omnibus' SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + 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/cygwin.yml b/.github/workflows/cygwin.yml new file mode 100644 index 0000000000..ac73991fe8 --- /dev/null +++ b/.github/workflows/cygwin.yml @@ -0,0 +1,71 @@ +name: Cygwin +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + runs-on: windows-2022 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - run: git config --global core.autocrlf input + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Setup Cygwin + uses: cygwin/cygwin-install-action@master + with: + packages: ruby gcc-core make autoconf libtool libssl-devel libyaml-devel libffi-devel zlib-devel rubygems + + - name: configure + run: | + ./autogen.sh + ./configure --disable-install-doc + shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0} + + - name: Extract bundled gems + run: | + make ruby -j5 + make extract-gems + shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0} + + - name: make all + timeout-minutes: 30 + run: make -j4 V=1 + shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0} + + - uses: ./.github/actions/slack + with: + label: Cygwin + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} diff --git a/.github/workflows/default_gems_list.yml b/.github/workflows/default_gems_list.yml new file mode 100644 index 0000000000..1c7e2195c8 --- /dev/null +++ b/.github/workflows/default_gems_list.yml @@ -0,0 +1,99 @@ +name: Update default gems list +on: [push, pull_request, merge_group] + +env: + UPDATE_NEWS_ENABLED: true + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + update_default_gems_list: + name: Update default gems list + + permissions: + contents: write # for Git to git push + + runs-on: ubuntu-latest + + if: ${{ github.repository == 'ruby/ruby' }} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} + + - id: gems + run: true + if: ${{ github.ref == 'refs/heads/master' }} + + - uses: ./.github/actions/setup/directories + with: + makeup: true + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN + checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) + if: ${{ steps.gems.outcome == 'success' }} + + - name: Download previous gems list + run: | + data=default_gems.json + mkdir -p .downloaded-cache + ln -s .downloaded-cache/$data . + curl -O -R -z ./$data https://stdgems.org/$data + if: ${{ steps.gems.outcome == 'success' }} + + - name: Make default gems list + run: | + #!ruby + require 'rubygems' + $:.unshift "lib" + rgver = File.foreach("lib/rubygems.rb") do |line| + break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line + end + gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f| + spec = Gem::Specification.load(f) + "#{spec.name} #{spec.version}" + end.sort + File.open("gems/default_gems", "w") do |f| + f.puts "RubyGems #{rgver}" + f.puts gems + end + shell: ruby --disable=gems {0} + if: ${{ steps.gems.outcome == 'success' }} + + - name: Maintain updated gems list in NEWS + run: | + ruby tool/update-NEWS-gemlist.rb default + if: ${{ steps.gems.outcome == 'success' && env.UPDATE_NEWS_ENABLED == 'true' }} + + - name: Check diffs + id: diff + run: | + git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md || + echo update=true >> $GITHUB_OUTPUT + if: ${{ steps.gems.outcome == 'success' }} + + - name: Commit + run: | + git pull --ff-only origin ${GITHUB_REF#refs/heads/} + git commit --message="Update default gems list at ${GITHUB_SHA:0:30} [ci skip]" NEWS.md + git push origin ${GITHUB_REF#refs/heads/} + env: + EMAIL: svn-admin@ruby-lang.org + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + if: >- + ${{ + github.repository == 'ruby/ruby' && + !startsWith(github.event_name, 'pull') && + steps.diff.outputs.update + }} + + - uses: ./.github/actions/slack + with: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} diff --git a/.github/workflows/dependabot_automerge.yml b/.github/workflows/dependabot_automerge.yml new file mode 100644 index 0000000000..a95c7005c4 --- /dev/null +++ b/.github/workflows/dependabot_automerge.yml @@ -0,0 +1,32 @@ +# from https://github.com/gofiber/swagger/blob/main/.github/workflows/dependabot_automerge.yml +name: Dependabot auto-merge +on: + pull_request: + +permissions: + contents: write + pull-requests: write + +jobs: + automerge: + runs-on: ubuntu-latest + if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'ruby/ruby' + steps: + - name: Dependabot metadata + uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0 + id: metadata + + - name: Wait for status checks + uses: lewagon/wait-on-check-action@3603e826ee561ea102b58accb5ea55a1a7482343 # v1.4.1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + check-regexp: 'make \(check, .*\)' + wait-interval: 30 + + - name: Auto-merge for Dependabot PRs + if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.update-type == 'version-update:semver-patch' }} + run: gh pr merge --auto --rebase "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GITHUB_TOKEN: ${{ secrets.MATZBOT_DEPENDABOT_MERGE_TOKEN }} diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000000..16dbac1afa --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,12 @@ +name: "Pull Request Labeler" +on: +- pull_request_target + +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v6 diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index daaea69ecb..29adcab39a 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -1,61 +1,201 @@ name: macOS -on: [push, pull_request] +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + jobs: make: strategy: matrix: - os: [macos-10.15, macos-11] - test_task: [ "check", "test-bundler-parallel" ] #, "test-bundled-gems" ] matrix tests has unknown issues + include: + - test_task: check + os: macos-14 + - test_task: check + os: macos-14 + configure_args: '--with-gcc=gcc-14' + - test_task: check + os: macos-14 + configure_args: '--with-jemalloc --with-opt-dir=$(brew --prefix jemalloc)' + - test_task: check + os: macos-14 + configure_args: '--with-gmp' + - test_task: test-all + test_opts: --repeat-count=2 + os: macos-14 + - test_task: test-bundler-parallel + os: macos-14 + - test_task: test-bundled-gems + os: macos-14 + - test_task: check + os: macos-15 fail-fast: false + env: - GITPULLOPTIONS: --no-tags origin ${{github.ref}} + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + runs-on: ${{ matrix.os }} + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + steps: - - run: mkdir build - working-directory: - - name: git config - run: | - git config --global advice.detachedHead 0 - git config --global init.defaultBranch garbage - - uses: actions/checkout@v2 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: - path: src + sparse-checkout-cone-mode: false + sparse-checkout: /.github + - name: Install libraries + uses: ./.github/actions/setup/macos + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + clean: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 0 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: make sure that kern.coredump=1 run: | - brew upgrade - brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline - working-directory: src - - name: Set ENV + 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: | - echo "JOBS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV - - run: ./autogen.sh - working-directory: src + 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 --with-openssl-dir=$(brew --prefix openssl@1.1) --with-readline-dir=$(brew --prefix readline) - - run: make $JOBS incs - - run: make $JOBS - - run: make leaked-globals - if: ${{ matrix.test_task == 'check' }} + run: ../src/configure -C --disable-install-doc ${ruby_configure_args} ${{ matrix.configure_args }} + - run: make prepare-gems - if: ${{ matrix.test_task == 'check' }} - - run: make $JOBS -s ${{ matrix.test_task }} - timeout-minutes: 60 + if: ${{ matrix.test_task == 'test-bundled-gems' }} + + - run: make + + - run: make hello + + - name: runirb + run: | + echo IRB::VERSION | make runirb RUNOPT="-- -f" + + - name: Set test options for skipped tests + run: | + set -x + TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')" + echo "TESTS=${TESTS}" >> $GITHUB_ENV + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: ${{ matrix.os }} + test-opts: ${{ matrix.test_opts }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + continue-on-error: true + timeout-minutes: 3 + + - name: Set extra test options + run: | + echo "TESTS=$TESTS ${{ matrix.test_opts }}" >> $GITHUB_ENV + echo "RUBY_TEST_TIMEOUT_SCALE=10" >> $GITHUB_ENV # With --repeat-count=2, flaky test by timeout occurs frequently for some reason + if: matrix.test_opts + + - name: make ${{ matrix.test_task }} + run: | + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + ulimit -c unlimited + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} + timeout-minutes: 90 + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + PRECHECK_BUNDLED_GEMS: 'no' + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} + + - name: make skipped tests + run: | + make -s test-all TESTS="${TESTS//-n!\//-n/}" env: - RUBY_TESTOPTS: "-q --tty=no" - TEST_BUNDLED_GEMS_ALLOW_FAILURES: "rexml" - - uses: k0kubun/action-slack@v2.0.0 + GNUMAKEFLAGS: '' + RUBY_TESTOPTS: '-v --tty=no' + PRECHECK_BUNDLED_GEMS: 'no' + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + + - name: CAPI extensions + uses: ./.github/actions/capiext with: - payload: | - { - "ci": "GitHub Actions", - "env": "${{ github.workflow }} / ${{ matrix.test_task }}", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } + builddir: build env: + RUBY_TESTOPTS: '-v --tty=no' + if: ${{ contains(matrix.extra_checks, 'capi') }} + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.os }} / ${{ matrix.test_task }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} + + - name: Resolve job ID + id: job_id + uses: actions/github-script@main + env: + matrix: ${{ toJson(matrix) }} + with: + script: | + const { data: workflow_run } = await github.rest.actions.listJobsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.runId + }); + const matrix = JSON.parse(process.env.matrix); + const job_name = `${context.job}${matrix ? ` (${Object.values(matrix).join(", ")})` : ""}`; + return workflow_run.jobs.find((job) => job.name === job_name).id; + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: macos-latest + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index d98f532cd7..5c639ad48b 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -1,149 +1,243 @@ name: MinGW -on: [push, pull_request] +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read # Notes: # Actions console encoding causes issues, see test-all & test-spec steps # jobs: make: - runs-on: windows-2019 + 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 -fstack-protector-strong" - CXXFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe" - CPPFLAGS: "-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048" - LDFLAGS: "-pipe -fstack-protector-strong" - UPDATE_UNICODE: "UNICODE_FILES=. UNICODE_PROPERTY_FILES=. UNICODE_AUXILIARY_FILES=. UNICODE_EMOJI_FILES=." - GITPULLOPTIONS: --no-tags origin ${{github.ref}} + MSYS2_ARCH: >- + ${{ + contains(matrix.msystem, 'arm64') && 'aarch64' || + contains(matrix.msystem, '64') && 'x86_64' || 'i686' + }} + MINGW_PACKAGE_PREFIX: >- + mingw-w${{ + endsWith(matrix.msystem, '64') && '64' || '32' + }}-${{ + startsWith(matrix.msystem, 'clang') && 'clang' || + startsWith(matrix.msystem, 'ucrt') && 'ucrt' || + 'mingw' + }}-${{ + contains(matrix.msystem, 'arm64') && 'aarch64' || + endsWith(matrix.msystem, '64') && 'x86_64' || 'i686' + }} + CFLAGS: '-mtune=generic -O3 -pipe' + CXXFLAGS: '-mtune=generic -O3 -pipe' + CPPFLAGS: '-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048' + LDFLAGS: '-pipe' + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + strategy: matrix: include: - - msystem: "MINGW64" - base_ruby: 2.6 - test_task: [ "check" ] # to make job names consistent - - msystem: "UCRT64" - base_ruby: head - test_task: [ "check" ] # to make job names consistent + # To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses. + # Ruby 3.2 is the first Windows Ruby to use OpenSSL 3.x + - msystem: 'UCRT64' + os: 2022 + test_task: 'check' + test-all-opts: '--name=!/TestObjSpace#test_reachable_objects_during_iteration/' + - msystem: 'CLANGARM64' + os: 11-arm + test_task: 'check' fail-fast: false + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + steps: - - run: mkdir build - working-directory: - - name: git config - run: | - git config --global core.autocrlf false - git config --global core.eol lf - git config --global advice.detachedHead 0 - git config --global init.defaultBranch garbage - - uses: actions/checkout@v2 + - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0 + id: msys2 with: - path: src - - name: Set up Ruby & MSYS2 - uses: MSP-Greg/setup-ruby-pkgs@ucrt - with: - ruby-version: ${{ matrix.base_ruby }} - setup-ruby-ref: MSP-Greg/ruby-setup-ruby/00-win-ucrt - mingw: _upgrade_ gmp libffi libyaml openssl ragel readline gcc - msys2: automake1.16 bison - - name: where check - run: | - # show where - Write-Host - $where = 'gcc.exe', 'ragel.exe', 'make.exe', 'bison.exe', 'libcrypto-1_1-x64.dll', 'libssl-1_1-x64.dll' - foreach ($e in $where) { - $rslt = where.exe $e 2>&1 | Out-String - if ($rslt.contains($e)) { Write-Host $rslt } - else { Write-Host "`nCan't find $e" } - } - - name: misc setup, autoreconf - run: | - mkdir install - mkdir temp - cd src - sh -c "autoreconf -fi" - working-directory: + 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: configure - run: | - # Actions uses UTF8, causes test failures, similar to normal OS setup - $PSDefaultParameterValues['*:Encoding'] = 'utf8' - [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") - [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") - $config_args = "--build=$env:CHOST --host=$env:CHOST --target=$env:CHOST" - Write-Host $config_args - sh -c "../src/configure --disable-install-doc --prefix=/install $config_args" - # Write-Host "-------------------------------------- config.log" - # Get-Content ./config.log | foreach {Write-Output $_} - - - name: update + - name: Set up env + id: setup-env + working-directory: run: | - $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS) - make -j $jobs incs + $msys2 = ${env:MSYS2_LOCATION} + $msystem = ${env:MSYSTEM}.ToLower() + echo $msys2\usr\bin $msys2\$msystem\bin | + Tee-Object ${env:GITHUB_PATH} -Append -Encoding utf-8 - - name: download gems + # 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: | - $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS) - make -j $jobs update-gems + Get-Command pkg-config.bat | % { ren $_.path ($_.path + "~") } + shell: pwsh - - name: make all - timeout-minutes: 40 + - name: Misc system & package info + working-directory: run: | - $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS) - make -j $jobs + group() { echo ::group::$'\e[94;1m'"$*"$'\e[m'; } + endgroup() { echo ::endgroup::; } - - run: make leaked-globals + group Path + cygpath -wa / . $(type -p cygpath bash sh) + endgroup + + I() { + group $1 + run Where type -pa $1 && { [ $# -eq 1 ] || run Version "$@"; } || + failed+=($1) + endgroup + } + run() { local w m=$1; shift; w="$("$@")" && show "$m" && indent "$w"; } + indent() { [ -z "$1" ] || echo "$1" | /bin/sed '/^$/!s/^/ /'; } + show() { echo $'\e[96m'"$*"$'\e[m'; } + + failed=() + + I gcc.exe --version + I ragel.exe --version + I make.exe --version + I openssl.exe version + I libcrypto-3-x64.dll + I libssl-3-x64.dll + + group Packages + pacman -Qs $MINGW_PACKAGE_PREFIX-* | /bin/sed -n "s,local/$MINGW_PACKAGE_PREFIX-,,p" + endgroup + + [ ${#failed[@]} -eq 0 ] + shell: sh + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: configure + run: > + ../src/configure --disable-install-doc --prefix=/. + --build=$CHOST --host=$CHOST --target=$CHOST + shell: sh + env: + CHOST: ${{ env.MSYS2_ARCH }}-w64-mingw32 + + - name: make all + timeout-minutes: 30 + run: make -j4 - name: make install - run: | - # Actions uses UTF8, causes test failures, similar to normal OS setup - $PSDefaultParameterValues['*:Encoding'] = 'utf8' - [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") - [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") - make DESTDIR=.. install-nodoc + 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: 5 - run: | - make test + timeout-minutes: 30 + run: make test test-tool + env: + GNUMAKEFLAGS: '' + RUBY_TESTOPTS: '-v --tty=no' + if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test' }} - name: test-all - timeout-minutes: 60 + timeout-minutes: 45 run: | - # Actions uses UTF8, causes test failures, similar to normal OS setup - $PSDefaultParameterValues['*:Encoding'] = 'utf8' - [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") - [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") - $jobs = [int](1.5 * $env:NUMBER_OF_PROCESSORS) - if ($env:BUNDLER_VERSION) { Remove-Item env:\BUNDLER_VERSION } - make test-all TESTOPTS="-j $jobs --retry --job-status=normal --show-skip --timeout-scale=1.5" + make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }} + env: + RUBY_TESTOPTS: >- + --retry --job-status=normal --show-skip --timeout-scale=1.5 -j4 + ${{ matrix.test-all-opts }} + ${{ env.TESTS }} + BUNDLER_VERSION: + if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-all' || StartsWith(matrix.test_task, 'test/') }} - name: test-spec timeout-minutes: 10 - working-directory: src/spec/ruby run: | - $env:Path = "$pwd/../../../install/bin;$env:Path" - # Actions uses UTF8, causes test failures, similar to normal OS setup - $PSDefaultParameterValues['*:Encoding'] = 'utf8' - [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") - [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437") - ruby -v - ruby ../mspec/bin/mspec -I../../tool/lib -j --timeout 60 - - - uses: k0kubun/action-slack@v2.0.0 + make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }} + if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/') }} + + - uses: ./src/.github/actions/slack with: - payload: | - { - "ci": "GitHub Actions", - "env": "${{ github.workflow }} / ${{ matrix.test_task }}", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } - env: + label: ${{ matrix.msystem }} / ${{ matrix.test_task }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} defaults: run: working-directory: build + shell: cmd diff --git a/.github/workflows/mjit.yml b/.github/workflows/mjit.yml deleted file mode 100644 index 63011e78d0..0000000000 --- a/.github/workflows/mjit.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: MJIT -on: [push, pull_request] -jobs: - make: - strategy: - matrix: - test_task: [ "check" ] # to make job names consistent - jit_opts: [ "--jit", "--jit-wait" ] - fail-fast: false - runs-on: ubuntu-latest - env: - TESTOPTS: '-q --tty=no' - RUN_OPTS: '--disable-gems ${{ matrix.jit_opts }} --jit-debug=-ggdb3' - GITPULLOPTIONS: --no-tags origin ${{github.ref}} - steps: - - run: mkdir build - working-directory: - - 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 libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby - - name: git config - run: | - git config --global advice.detachedHead 0 - git config --global init.defaultBranch garbage - - uses: actions/checkout@v2 - with: - path: src - - name: Fixed world writable dirs - run: | - chmod -v go-w $HOME $HOME/.config - sudo chmod -R go-w /usr/share - sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : - - name: Set ENV - run: | - echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV - - run: ./autogen.sh - working-directory: src - - name: Run configure - run: ../src/configure -C --disable-install-doc cppflags=-DVM_CHECK_MODE - - run: make $JOBS incs - - run: make $JOBS - - run: sudo make $JOBS -s install - - run: sudo apt-get install gdb # used by test / test-all failure - - name: Run test - run: | - ulimit -c unlimited - make $JOBS -s test RUN_OPTS="$RUN_OPTS" - timeout-minutes: 60 - - name: Run test-all - run: | - ulimit -c unlimited - make $JOBS -s test-all RUN_OPTS="$RUN_OPTS" - timeout-minutes: 60 - - name: Run test-spec - run: | - ulimit -c unlimited - make $JOBS -s test-spec RUN_OPTS="$RUN_OPTS" - timeout-minutes: 60 - - uses: k0kubun/action-slack@v2.0.0 - with: - payload: | - { - "ci": "GitHub Actions", - "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.jit_opts }}", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} - -defaults: - run: - working-directory: build diff --git a/.github/workflows/modgc.yml b/.github/workflows/modgc.yml new file mode 100644 index 0000000000..1d14934df8 --- /dev/null +++ b/.github/workflows/modgc.yml @@ -0,0 +1,176 @@ +name: ModGC +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + check: + strategy: + matrix: + gc: + - name: default + - name: mmtk + mmtk_build: release + os: [macos-latest, ubuntu-latest] + include: + - test_task: check + fail-fast: false + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUBY_DEBUG: ci + + runs-on: ${{ matrix.os }} + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - name: Install libraries (macOS) + uses: ./.github/actions/setup/macos + if: ${{ contains(matrix.os, 'macos') }} + + - name: Install libraries (Ubuntu) + uses: ./.github/actions/setup/ubuntu + if: ${{ contains(matrix.os, 'ubuntu') }} + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.1' + bundler: none + if: ${{ contains(matrix.os, 'ubuntu') }} + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + clean: true + dummy-files: false + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: make sure that kern.coredump=1 + run: | + sysctl -n kern.coredump + sudo sysctl -w kern.coredump=1 + sudo chmod -R +rwx /cores/ + if: ${{ contains(matrix.os, 'macos') }} + + - name: Delete unused SDKs + # To free up disk space to not run out during the run + run: | + sudo rm -rf ~/.dotnet + sudo rm -rf /Library/Android + sudo rm -rf /Library/Developer/CoreSimulator + continue-on-error: true + if: ${{ contains(matrix.os, 'macos') }} + + - name: Setup Ruby GC Directory + run: | + echo "MODULAR_GC_DIR=$HOME/ruby_gc" >> $GITHUB_ENV + + - name: Run configure + env: + arch: ${{ matrix.arch }} + run: >- + $SETARCH ../src/configure -C --disable-install-doc --with-modular-gc=${{ env.MODULAR_GC_DIR }} + ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + - name: Set MMTk environment variables + run: | + echo 'EXCLUDES=../src/test/.excludes-mmtk' >> $GITHUB_ENV + echo 'MSPECOPT=-B../src/spec/mmtk.mspec' >> $GITHUB_ENV + if: ${{ matrix.gc.name == 'mmtk' }} + + - run: $SETARCH make + + - name: Build Modular GC + run: | + echo "RUBY_GC_LIBRARY=${{ matrix.gc.name }}" >> $GITHUB_ENV + make install-modular-gc MODULAR_GC=${{ matrix.gc.name }} MMTK_BUILD=${{ matrix.gc.mmtk_build }} + make distclean-modular-gc MODULAR_GC=${{ matrix.gc.name }} + + - run: $SETARCH make hello + + - name: Set test options for skipped tests + run: | + set -x + TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')" + echo "TESTS=${TESTS}" >> $GITHUB_ENV + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: ${{ matrix.os || 'ubuntu-22.04' }} + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + continue-on-error: true + timeout-minutes: 3 + + - name: make ${{ matrix.test_task }} + run: | + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + $SETARCH make -s ${{ matrix.test_task }} \ + ${TESTS:+TESTS="$TESTS"} \ + ${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }} + timeout-minutes: ${{ matrix.gc.timeout || 40 }} + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + PRECHECK_BUNDLED_GEMS: 'no' + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} + + - name: make skipped tests + run: | + $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}" + env: + GNUMAKEFLAGS: '' + RUBY_TESTOPTS: '-v --tty=no' + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/parse_y.yml b/.github/workflows/parse_y.yml new file mode 100644 index 0000000000..87facc8a55 --- /dev/null +++ b/.github/workflows/parse_y.yml @@ -0,0 +1,100 @@ +name: parse.y +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + matrix: + include: + - test_task: check + - test_task: test-bundler-parallel + - test_task: test-bundled-gems + fail-fast: false + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUBY_DEBUG: ci + SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }} + + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/ubuntu + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.1' + bundler: none + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + clean: true + dummy-files: ${{ matrix.test_task == 'check' }} + + - name: Run configure + run: ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG --with-parser=parse.y + + - run: make + + - run: make TESTRUN_SCRIPT='-renvutil -v -e "exit EnvUtil.current_parser == %[parse.y]"' run + env: + RUNOPT0: -I$(tooldir)/lib + + - name: make ${{ matrix.test_task }} + run: make -s ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" SPECOPTS="$SPECOPTS" + env: + RUBY_TESTOPTS: ${{ matrix.testopts }} + EXCLUDES: '../src/test/.excludes-parsey' + RUN_OPTS: ${{ matrix.run_opts || '--parser=parse.y' }} + SPECOPTS: ${{ matrix.specopts || '-T --parser=parse.y' }} + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.run_opts }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/post_push.yml b/.github/workflows/post_push.yml new file mode 100644 index 0000000000..318444c0a2 --- /dev/null +++ b/.github/workflows/post_push.yml @@ -0,0 +1,85 @@ +name: Post-push +on: + push: + branches: + - master + - 'ruby_*_*' +jobs: + hooks: + name: Post-push hooks + runs-on: ubuntu-latest + if: ${{ github.repository == 'ruby/ruby' }} + steps: + - name: Sync git.ruby-lang.org + run: | + mkdir -p ~/.ssh + (umask 066; printenv RUBY_GIT_SYNC_PRIVATE_KEY > ~/.ssh/id_ed25519) + ssh-keyscan -t ed25519 git.ruby-lang.org >> ~/.ssh/known_hosts + ssh -i ~/.ssh/id_ed25519 git-sync@git.ruby-lang.org "sudo -u git /home/git/git.ruby-lang.org/bin/update-ruby.sh $GITHUB_REF" + env: + GITHUB_REF: ${{ github.ref }} + RUBY_GIT_SYNC_PRIVATE_KEY: ${{ secrets.RUBY_GIT_SYNC_PRIVATE_KEY }} + if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }} + + - name: Fetch changesets on bugs.ruby-lang.org + run: | + curl "https://bugs.ruby-lang.org/sys/fetch_changesets?key=${REDMINE_SYS_API_KEY}" -s --fail-with-body -w '* status: %{http_code}\n' + env: + REDMINE_SYS_API_KEY: ${{ secrets.REDMINE_SYS_API_KEY }} + if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }} + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + fetch-depth: 500 # for notify-slack-commits + token: ${{ secrets.MATZBOT_AUTO_UPDATE_TOKEN }} + + - name: Notify commit to Slack + run: ruby tool/notify-slack-commits.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master + env: + GITHUB_OLD_SHA: ${{ github.event.before }} + GITHUB_NEW_SHA: ${{ github.event.after }} + SLACK_WEBHOOK_URL_ALERTS: ${{ secrets.SLACK_WEBHOOK_URL_ALERTS }} + SLACK_WEBHOOK_URL_COMMITS: ${{ secrets.SLACK_WEBHOOK_URL_COMMITS }} + SLACK_WEBHOOK_URL_RUBY_JP: ${{ secrets.SLACK_WEBHOOK_URL_RUBY_JP }} + if: ${{ github.ref == 'refs/heads/master' }} + + - name: Notify commit to ruby-cvs + run: | + SENDMAIL="ssh -i ${HOME}/.ssh/id_ed25519 git-sync@git.ruby-lang.org /usr/sbin/sendmail" \ + ruby tool/commit-email.rb . ruby-cvs@g.ruby-lang.org \ + "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" "$GITHUB_REF" \ + --viewer-uri "https://github.com/ruby/ruby/commit/" \ + --error-to cvs-admin@ruby-lang.org + env: + GITHUB_OLD_SHA: ${{ github.event.before }} + GITHUB_NEW_SHA: ${{ github.event.after }} + GITHUB_REF: ${{ github.ref }} + if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }} + + - name: Auto-correct code styles + run: | + set -x + ruby tool/auto-style.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master + env: + GITHUB_OLD_SHA: ${{ github.event.before }} + GITHUB_NEW_SHA: ${{ github.event.after }} + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + EMAIL: svn-admin@ruby-lang.org + if: ${{ github.ref == 'refs/heads/master' }} + + - name: Push PR notes to GitHub + run: ruby tool/notes-github-pr.rb "$(pwd)/.git" "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master + env: + GITHUB_OLD_SHA: ${{ github.event.before }} + GITHUB_NEW_SHA: ${{ github.event.after }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + EMAIL: svn-admin@ruby-lang.org + if: ${{ github.ref == 'refs/heads/master' }} + + - uses: ./.github/actions/slack + with: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} diff --git a/.github/workflows/pr-playground.yml b/.github/workflows/pr-playground.yml new file mode 100644 index 0000000000..f3c0556429 --- /dev/null +++ b/.github/workflows/pr-playground.yml @@ -0,0 +1,127 @@ +name: Post Playground link to PR +on: + pull_request_target: + types: [labeled] + workflow_run: + workflows: ["WebAssembly"] + types: [completed] + +jobs: + post-summary: + name: Post Playground link + runs-on: ubuntu-latest + permissions: + pull-requests: write + # Post a comment only if the PR status check is passed and the PR is labeled with `Playground`. + # Triggered twice: when the PR is labeled and when PR build is passed. + if: >- + ${{ false + || (true + && github.event_name == 'pull_request_target' + && contains(github.event.pull_request.labels.*.name, 'Playground')) + || (true + && github.event_name == 'workflow_run' + && github.event.workflow_run.conclusion == 'success' + && github.event.workflow_run.event == 'pull_request') + }} + steps: + - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs/promises'); + + const buildWorkflowPath = '.github/workflows/wasm.yml'; + const findSuccessfuBuildRun = async (pr) => { + const opts = github.rest.actions.listWorkflowRunsForRepo.endpoint.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + status: 'success', + branch: pr.head.ref, + }); + const runs = await github.paginate(opts); + const buildRun = runs.find(run => run.path == buildWorkflowPath); + return buildRun; + } + + const postComment = async (body, pr) => { + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + }); + + const commentOpts = { owner: context.repo.owner, repo: context.repo.repo, body: comment }; + + const existingComment = comments.find(comment => comment.body.startsWith(magicComment)); + if (existingComment) { + core.info(`Updating existing comment: ${existingComment.html_url}`); + await github.rest.issues.updateComment({ + ...commentOpts, comment_id: existingComment.id + }); + } else { + await github.rest.issues.createComment({ + ...commentOpts, issue_number: pr.number + }); + } + } + + const derivePRNumber = async () => { + if (context.payload.pull_request) { + return context.payload.pull_request.number; + } + // Workaround for https://github.com/orgs/community/discussions/25220 + + const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + const artifact = artifacts.find(artifact => artifact.name == 'github-pr-info'); + if (!artifact) { + throw new Error('Cannot find github-pr-info.txt artifact'); + } + + const { data } = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: artifact.id, + archive_format: 'zip', + }); + + await fs.writeFile('pr-info.zip', Buffer.from(data)); + await exec.exec('unzip', ['pr-info.zip']); + return await fs.readFile('github-pr-info.txt', 'utf8'); + } + + const prNumber = await derivePRNumber(); + + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + + core.info(`Checking if the PR ${prNumber} is labeled with Playground...`); + if (!pr.labels.some(label => label.name == 'Playground')) { + core.info(`The PR is not labeled with Playground.`); + return; + } + + core.info(`Checking if the build is successful for ${pr.head.ref} in ${pr.head.repo.owner.login}/${pr.head.repo.name}...`); + const buildRun = await findSuccessfuBuildRun(pr); + if (!buildRun) { + core.info(`No successful build run found for ${buildWorkflowPath} on ${pr.head.ref} yet.`); + return; + } + core.info(`Found a successful build run: ${buildRun.html_url}`); + + const runLink = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`; + const magicComment = `<!-- AUTO-GENERATED-COMMENT-PR-PLAYGROUND -->`; + const comment = `${magicComment} + **Try on Playground**: https://ruby.github.io/play-ruby?run=${buildRun.id} + This is an automated comment by [\`pr-playground.yml\`](${runLink}) workflow. + `; + core.info(`Comment: ${comment}`); + await postComment(comment, pr); + diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000..3caeee9a3b --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,107 @@ +name: Publish Ruby packages + +on: + repository_dispatch: + types: + - release + workflow_dispatch: + inputs: + version: + description: 'Version of the Ruby package to release' + required: true + default: '3.3.4' + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6.0.1 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.3.4 + + - name: Store Ruby version + run: | + echo "RUBY_VERSION=${{ github.event.client_payload.version || github.event.inputs.version }}" >> $GITHUB_ENV + + - name: Store ABI version + run: echo "ABI_VERSION=$(echo ${{ env.RUBY_VERSION }} | cut -d '.' -f 1-2)" >> $GITHUB_ENV + + - name: Copy draft package `/tmp` to `/pub` directory + run: tool/release.sh ${{ env.RUBY_VERSION }} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.FTP_R_L_O_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.FTP_R_L_O_AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: us-west-2 + + - name: Purge URLs of release package + run: | + curl -X POST \ + -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \ + https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.tar.gz + curl -X POST \ + -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \ + https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.tar.xz + curl -X POST \ + -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \ + https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.zip + + - name: Create a release on GitHub + run: | + RELEASE_TAG=$(ruby tool/ruby-version.rb tag "${{ env.RUBY_VERSION }}") + echo $RELEASE_TAG + PREVIOUS_RELEASE_TAG=$(ruby tool/ruby-version.rb previous-tag "${{ env.RUBY_VERSION }}") + echo $PREVIOUS_RELEASE_TAG + tool/gen-github-release.rb $PREVIOUS_RELEASE_TAG $RELEASE_TAG --no-dry-run + env: + GITHUB_TOKEN: ${{ secrets.MATZBOT_AUTO_UPDATE_TOKEN }} + + - name: Update versions index + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/actions/dispatches \ + -d '{"event_type": "update_index"}' + + - name: Build and push Docker images + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/docker-images/actions/workflows/build.yml/dispatches \ + -d '{"ref": "master", "inputs": {"ruby_version": "${{ env.RUBY_VERSION }}"}}' + + - name: Build snapcraft packages + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/snap.ruby/dispatches \ + -d '{"event_type": "build", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}"}}' + + - name: Store the latest LTS version of OpenSSL + run: | + echo "OPENSSL_VERSION=`curl -s https://api.github.com/repos/openssl/openssl/releases | jq -r '.[].tag_name | select(startswith("openssl-3.0"))' | sort -Vr | head -n1 | cut -d'-' -f2`" >> $GITHUB_ENV + + - name: Update ruby-build definition + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.RUBY_BUILD_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/rbenv/ruby-build/dispatches \ + -d '{"event_type": "update-ruby", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}", "openssl_version": "${{ env.OPENSSL_VERSION }}"}}' + + - name: Update all-ruby definition + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/all-ruby/dispatches \ + -d '{"event_type": "update"}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..5d4474d978 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,18 @@ +name: Start release workflow +on: + push: + tags: + - '*' + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - name: Build release package + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/actions/dispatches \ + -d '{"event_type": "${{ github.ref }}"}' diff --git a/.github/workflows/rust-warnings.yml b/.github/workflows/rust-warnings.yml new file mode 100644 index 0000000000..a2e3208e52 --- /dev/null +++ b/.github/workflows/rust-warnings.yml @@ -0,0 +1,60 @@ +# Surface Rust warnings on PRs that touch any Rust code. +# Not a required check so we never block people over new warnings +# that might come from a new Rust version being released. +name: Rust warnings +on: + pull_request: + types: + - opened + - synchronize + - reopened + paths: + - '**.rs' + - '!**.inc.rs' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + rust-warnings: + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + + runs-on: ubuntu-24.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Install Rust + run: rustup default beta + + - name: Rust warnings + shell: bash + run: | + set -eu + cargo check --quiet --all-features --message-format=json \ + | jq -r 'select(.message.level | IN("warning", "error")) | .message.rendered' \ + | tee messages.txt + (exit "${PIPESTATUS[0]}") && ! grep --quiet '[^[:space:]]' messages.txt + + - name: "📜 `rustdoc` warnings" + shell: bash + run: | + set -eu + cargo doc --document-private-items --all --no-deps --message-format=json \ + | jq -r 'select(.message.level | IN("warning", "error")) | .message.rendered' \ + | tee messages.txt + (exit "${PIPESTATUS[0]}") && ! grep --quiet '[^[:space:]]' messages.txt diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml new file mode 100644 index 0000000000..c607098997 --- /dev/null +++ b/.github/workflows/scorecards.yml @@ -0,0 +1,78 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '39 3 * * 5' + # push: + # branches: [ "master" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled. + if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request' + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore + # file_mode: git + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: results.sarif diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index 61ebeb33c1..cf4661555c 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -1,38 +1,67 @@ name: Rubyspec Version Guards Check -on: [push, pull_request] +on: + push: + paths: + - '.github/workflows/spec_guards.yml' + - 'spec/**' + - '!spec/*.md' + pull_request: + paths: + - '.github/workflows/spec_guards.yml' + - 'spec/**' + - '!spec/*.md' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read jobs: rubyspec: name: Rubyspec - runs-on: ubuntu-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.event.pull_request.user.login == 'dependabot[bot]') + )}} + strategy: matrix: # Specs from ruby/spec should still run on all supported Ruby versions. # This also ensures the needed ruby_version_is guards are there, see spec/README.md. ruby: - - ruby-2.7 - - ruby-3.0 + - ruby-3.2 + - ruby-3.3 + - ruby-3.4 + - ruby-4.0 + fail-fast: false steps: - - uses: actions/checkout@v2 - - uses: ruby/setup-ruby@v1 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 with: ruby-version: ${{ matrix.ruby }} bundler: none + - run: gem install webrick + - run: ruby ../mspec/bin/mspec working-directory: spec/ruby - - uses: k0kubun/action-slack@v2.0.0 - with: - payload: | - { - "ci": "GitHub Actions", - "env": "${{ github.workflow }} / rubyspec @ ${{ matrix.ruby }}", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } env: + CHECK_LEAKS: true + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.ruby }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} diff --git a/.github/workflows/sync_default_gems.yml b/.github/workflows/sync_default_gems.yml new file mode 100644 index 0000000000..9ff97d5a4e --- /dev/null +++ b/.github/workflows/sync_default_gems.yml @@ -0,0 +1,77 @@ +name: Sync default gems + +env: + DEFAULT_GEM_SYNC_ENABLED: true + +on: + workflow_dispatch: + inputs: + gem: + required: true + description: 'Name of the gem to be synchronized' + type: string + before: + required: true + description: 'Gem commit SHA before sync' + type: string + after: + required: true + description: 'Gem commit SHA after sync' + type: string + +jobs: + sync_default_gems: + name: Sync default gem ${{ github.event.inputs.gem }} + + permissions: + contents: write # for Git to git push + + runs-on: ubuntu-latest + + if: ${{ github.repository == 'ruby/ruby' }} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + name: Check out ruby/ruby + with: + token: ${{ github.repository == 'ruby/ruby' && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.4' + bundler: none + + - name: Run tool/sync_default_gems.rb + id: sync + run: | + ruby_before=$(git rev-parse HEAD) + set -x + ruby tool/sync_default_gems.rb "${gem_name}" "${gem_before}..${gem_after}" + if [[ "$(git rev-parse HEAD)" != "$ruby_before" ]]; then + echo update=true >> $GITHUB_OUTPUT + fi + env: + gem_name: ${{ github.event.inputs.gem }} + gem_before: ${{ github.event.inputs.before }} + gem_after: ${{ github.event.inputs.after }} + EMAIL: svn-admin@ruby-lang.org + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + + - name: Push + run: | + git pull --rebase origin ${GITHUB_REF#refs/heads/} + git push origin ${GITHUB_REF#refs/heads/} + if: ${{ steps.sync.outputs.update && env.DEFAULT_GEM_SYNC_ENABLED == 'true' }} + env: + EMAIL: svn-admin@ruby-lang.org + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + + - uses: ./.github/actions/slack + with: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + label: "${{ github.event.inputs.gem }} (<https://github.com/${{ github.event.inputs.gem == 'rubygems' && 'rubygems' || 'ruby' }}/${{ github.event.inputs.gem }}/compare/${{ github.event.inputs.before }}...${{ github.event.inputs.after }}|diff>)" + event_name: workflow_dispatch + extra_channel_id: C05FPKAU743 # alerts-sync + if: ${{ failure() }} diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index e148b76cbe..88c19b6fe6 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -1,78 +1,268 @@ name: Ubuntu -on: [push, pull_request] +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + jobs: make: strategy: matrix: - test_task: ["check", "test-bundler-parallel", "test-bundled-gems"] - os: - - ubuntu-20.04 -# - ubuntu-18.04 - configure: ["", "cppflags=-DRUBY_DEBUG"] + # We enumerate every job in matrix.include to save build time include: - - test_task: "test-all TESTS=--repeat-count=2" - os: ubuntu-20.04 - configure: "" + - 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: - GITPULLOPTIONS: --no-tags origin ${{github.ref}} + + env: &make-env + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} RUBY_DEBUG: ci - runs-on: ${{ matrix.os }} - steps: - - run: mkdir build - working-directory: - - name: Install libraries + + runs-on: ${{ matrix.os || 'ubuntu-22.04' }} + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: &make-steps + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/ubuntu + with: + arch: ${{ matrix.arch }} + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.1' + bundler: none + if: >- + ${{ !endsWith(matrix.os, 'arm') + && !endsWith(matrix.os, 'ppc64le') && !endsWith(matrix.os, 's390x') }} + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + clean: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: Run configure + env: + arch: ${{ matrix.arch }} + configure: ${{ matrix.configure }} + run: >- + $SETARCH ../src/configure -C --disable-install-doc ${configure:-cppflags=-DRUBY_DEBUG} + ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} + + - run: $SETARCH make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + + - run: $SETARCH make + + - run: $SETARCH make hello + + - name: runirb run: | - set -x - sudo apt-get update -q || : - sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby - - name: git config + echo IRB::VERSION | $SETARCH make runirb RUNOPT="-- -f" + + - name: Set test options for skipped tests run: | - git config --global advice.detachedHead 0 - git config --global init.defaultBranch garbage - - uses: actions/checkout@v2 + 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: - path: src - - name: Fixed world writable dirs - run: | - chmod -v go-w $HOME $HOME/.config - sudo chmod -R go-w /usr/share - sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : - - name: Set ENV + 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: | - echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV - - run: ./autogen.sh - working-directory: src - - name: Run configure - run: ../src/configure -C --disable-install-doc ${{ matrix.configure }} - - run: make $JOBS incs - - run: make $JOBS - - run: make leaked-globals - if: ${{ matrix.test_task == 'check' }} - - run: make prepare-gems - if: ${{ matrix.test_task == 'check' }} - - name: Create dummy files in build dir + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + $SETARCH make -s ${{ matrix.test_task }} \ + ${TESTS:+TESTS="$TESTS"} \ + ${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }} + timeout-minutes: ${{ matrix.timeout || 40 }} + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + PRECHECK_BUNDLED_GEMS: 'no' + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} + + - name: make skipped tests run: | - ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}' - if: ${{ matrix.test_task == 'check' }} - - run: make $JOBS -s ${{ matrix.test_task }} - timeout-minutes: 30 + $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}" env: - RUBY_TESTOPTS: "-q --tty=no" - TEST_BUNDLED_GEMS_ALLOW_FAILURES: "" - - uses: k0kubun/action-slack@v2.0.0 + GNUMAKEFLAGS: '' + RUBY_TESTOPTS: '-v --tty=no' + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + + - name: test-pc + run: | + DESTDIR=${RUNNER_TEMP-${TMPDIR-/tmp}}/installed + $SETARCH make test-pc "DESTDIR=$DESTDIR" + + - name: CAPI extensions + uses: ./.github/actions/capiext with: - payload: | - { - "ci": "GitHub Actions", - "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } + builddir: build + make: '$SETARCH make' env: + RUBY_TESTOPTS: '-v --tty=no' + if: ${{ contains(matrix.extra_checks, 'capi') }} + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}${{ matrix.os }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + + make-ibm: + strategy: + matrix: + include: + - test_task: check + os: ubuntu-24.04-ppc64le + - test_task: check + os: ubuntu-24.04-s390x + fail-fast: false + + env: *make-env + + runs-on: ${{ matrix.os }} + + if: >- + ${{github.repository == 'ruby/ruby' + && !(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: *make-steps + + # Separated from `make` job to avoid making it a required status check + ruby-bench: + strategy: + matrix: + include: + # Using the same setup as ZJIT jobs + - bench_opts: '--warmup=1 --bench=1 --excludes=lobsters' + + runs-on: ubuntu-24.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: ./.github/actions/setup/ubuntu + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + + - name: Run configure + run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install" + + - run: make install + + - name: Checkout ruby-bench + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + repository: ruby/ruby-bench + path: ruby-bench + + # If you want to skip failing benchmark, consider using `--excludes`. + # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'` + - name: Run ruby-bench + run: ruby run_benchmarks.rb -e "ruby::../build/install/bin/ruby" ${{ matrix.bench_opts }} + working-directory: ruby-bench + + - uses: ./.github/actions/slack + with: + label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: ubuntu-latest + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml new file mode 100644 index 0000000000..0d2a6f0545 --- /dev/null +++ b/.github/workflows/wasm.yml @@ -0,0 +1,179 @@ +name: WebAssembly +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: # added using https://github.com/step-security/secure-workflows + contents: read + +jobs: + make: + strategy: + matrix: + entry: +# # wasmtime can't compile non-optimized Asyncified binary due to locals explosion +# - { name: O0-debuginfo, optflags: '-O0', debugflags: '-g', wasmoptflags: '-O1' } +# - { name: O1, optflags: '-O1', debugflags: '' , wasmoptflags: '-O1' } + - { name: O2, optflags: '-O2', debugflags: '', wasmoptflags: '-O2' } +# - { name: O3, optflags: '-O3', debugflags: '' , wasmoptflags: '-O3' } +# # -O4 is equivalent to -O3 in clang, but it's different in wasm-opt +# - { name: O4, optflags: '-O3', debugflags: '' , wasmoptflags: '-O4' } +# - { name: Oz, optflags: '-Oz', debugflags: '' , wasmoptflags: '-Oz' } + fail-fast: false + + env: + RUBY_TESTOPTS: '-q --tty=no' + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + WASI_SDK_VERSION_MAJOR: 25 + WASI_SDK_VERSION_MINOR: 0 + BINARYEN_VERSION: 113 + WASMTIME_VERSION: v15.0.0 + + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + + - name: Install libraries + run: | + set -ex + sudo apt-get update -q || : + sudo apt-get install --no-install-recommends -q -y ruby make autoconf git wget + + wasi_sdk_deb="wasi-sdk-${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}-x86_64-linux.deb" + wget "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION_MAJOR}/${wasi_sdk_deb}" + sudo dpkg -i "$wasi_sdk_deb" + rm -f "$wasi_sdk_deb" + + mkdir build-sdk + pushd build-sdk + + wasmtime_url="https://github.com/bytecodealliance/wasmtime/releases/download/${WASMTIME_VERSION}/wasmtime-${WASMTIME_VERSION}-x86_64-linux.tar.xz" + wget -O - "$wasmtime_url" | tar xJf - + sudo ln -fs "$PWD/wasmtime-${WASMTIME_VERSION}-x86_64-linux/wasmtime" /usr/local/bin/wasmtime + + binaryen_tarball="binaryen-version_${BINARYEN_VERSION}-x86_64-linux.tar.gz" + binaryen_url="https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VERSION}/${binaryen_tarball}" + wget -O - "$binaryen_url" | tar xfz - + sudo ln -fs "$PWD/binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt" /usr/local/bin/wasm-opt + working-directory: src + + - name: Set ENV + run: | + echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.1' + bundler: none + + - name: Build baseruby + run: | + set -ex + mkdir ../baseruby + pushd ../baseruby + ../src/configure --prefix=$PWD/install + make + make install + + - name: Download config.guess with wasi version + run: | + rm tool/config.guess tool/config.sub + ruby tool/downloader.rb -d tool -e gnu config.guess config.sub + working-directory: src + + - name: Run configure + run: | + ../src/configure \ + --host wasm32-unknown-wasi \ + --with-baseruby=$PWD/../baseruby/install/bin/ruby \ + --with-static-linked-ext \ + --with-ext=cgi/escape,continuation,coverage,date,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,json,json/generator,json/parser,objspace,pathname,rbconfig/sizeof,ripper,stringio,strscan,monitor \ + LDFLAGS=" \ + -Xlinker --stack-first \ + -Xlinker -z -Xlinker stack-size=16777216 \ + " \ + optflags="${{ matrix.entry.optflags }}" \ + debugflags="${{ matrix.entry.debugflags }}" \ + wasmoptflags="${{ matrix.entry.wasmoptflags }} ${{ matrix.entry.debugflags }}" + + # miniruby may not be built when cross-compling + - run: make mini ruby + + - run: make install DESTDIR=$PWD/../install + - run: tar cfz ../install.tar.gz -C ../install . + + - name: Upload artifacts + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + with: + name: ruby-wasm-install + path: ${{ github.workspace }}/install.tar.gz + - name: Show Playground URL to try the build + run: | + echo "Try on Playground: https://ruby.github.io/play-ruby?run=$GITHUB_RUN_ID" >> $GITHUB_STEP_SUMMARY + + - name: Run basictest + run: wasmtime run ./../build/miniruby --mapdir /::./ -- basictest/test.rb + working-directory: src + + - name: Run bootstraptest (no thread) + run: | + NO_THREAD_TESTS="$(grep -L Thread -R ./bootstraptest | awk -F/ '{ print $NF }' | uniq | sed -n 's/test_\(.*\).rb/\1/p' | paste -s -d, -)" + ruby ./bootstraptest/runner.rb --ruby="$(which wasmtime) run $PWD/../build/ruby --mapdir /::./ -- " --verbose "--sets=$NO_THREAD_TESTS" + working-directory: src + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.entry.name }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + + # Workaround for https://github.com/orgs/community/discussions/25220 + - name: Save Pull Request number + if: ${{ github.event_name == 'pull_request' }} + run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + if: ${{ github.event_name == 'pull_request' }} + with: + name: github-pr-info + path: ${{ github.workspace }}/github-pr-info.txt + +defaults: + run: + working-directory: build diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 66b2992049..1d44a5482c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,122 +1,199 @@ name: Windows -on: [push, pull_request] +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + jobs: make: strategy: matrix: include: - - vs: 2019 - os: windows-2019 - vcvars: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"' - # - vs: 2022 - # os: windows-2022 - # vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Auxiliary\Build\vcvars64.bat"' + - os: 2022 + vc: 2022 + test_task: check + - os: 2025 + vc: 2022 + test_task: check + - os: 11-arm + test_task: 'btest test-basic test-tool' # check and test-spec are broken yet. + target: arm64 + - os: 2025 + vc: 2022 + test_task: test-bundled-gems fail-fast: false - runs-on: ${{ matrix.os }} - name: VisualStudio ${{ 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.event.pull_request.user.login == 'dependabot[bot]') + )}} + + name: Windows ${{ matrix.os }}/Visual C++ ${{ matrix.vc }} (${{ matrix.test_task }}) + env: - GITPULLOPTIONS: --no-tags origin ${{github.ref}} - VCVARS: ${{ matrix.vcvars }} - PATCH: C:\msys64\usr\bin\patch.exe + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + VCPKG_DEFAULT_TRIPLET: ${{ matrix.target || 'x64' }}-windows + steps: - run: md build working-directory: - - uses: msys2/setup-msys2@v2 - id: setup-msys2 + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 with: - update: true - install: >- - patch - if: ${{ matrix.os != 'windows-2019' }} - - 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@v2 + # windows-11-arm has only 3.4.1, 3.4.2, 3.4.3, head + ruby-version: ${{ !endsWith(matrix.os, 'arm') && '3.1' || '3.4' }} + bundler: none + windows-toolchain: none + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: - path: C:\vcpkg\downloads - key: ${{ runner.os }}-vcpkg-download-${{ matrix.os }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-vcpkg-download-${{ matrix.os }}- - ${{ runner.os }}-vcpkg-download- - - name: Install libraries with vcpkg - run: | - vcpkg --triplet x64-windows install readline zlib - - uses: actions/cache@v2 + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/directories with: - path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey - key: ${{ runner.os }}-chocolatey-${{ matrix.os }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-chocolatey-${{ matrix.os }}- - ${{ runner.os }}-chocolatey- - - name: Install libraries with chocolatey + srcdir: src + builddir: build + make-command: nmake + clean: true + + - name: Install tools with scoop run: | - # Using Choco-Install for retries, but it doesn't detect failures properly - # if you pass multiple package names in a single command. - Choco-Install -PackageName openssl - Choco-Install -PackageName winflexbison3 + Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + iwr -useb get.scoop.sh | iex + Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH + scoop install vcpkg uutils-coreutils shell: pwsh - - name: git config + + - name: Restore vcpkg artifact + id: restore-vcpkg + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + with: + path: src\vcpkg_installed + key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }} + + - name: Install libraries with vcpkg run: | - git config --global core.autocrlf false - git config --global core.eol lf - git config --global advice.detachedHead 0 - git config --global init.defaultBranch garbage - - uses: actions/checkout@v2 + vcpkg install --vcpkg-root=%USERPROFILE%\scoop\apps\vcpkg\current + working-directory: src + if: ${{ ! steps.restore-vcpkg.outputs.cache-hit }} + + - name: Save vcpkg artifact + uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: - path: src + 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 | C:\msys64\usr\bin\sort > old.env - call %VCVARS% - set TMP=%USERPROFILE%\AppData\Local\Temp - set TEMP=%USERPROFILE%\AppData\Local\Temp - set | C:\msys64\usr\bin\sort > new.env - C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV% + ::- Set up VC ${{ matrix.vc }} + set | sort > old.env + call ..\src\win32\vssetup.cmd ^ + -arch=${{ matrix.target || 'amd64' }} ^ + ${{ matrix.vcvars && '-vcvars_ver=' || '' }}${{ matrix.vcvars }} + nmake -f nul + set TMP=%RUNNER_TEMP% + set TEMP=%RUNNER_TEMP% + set MAKEFLAGS=l + set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul + set RUBY_OPT_DIR=%GITHUB_WORKSPACE:\=/%/src/vcpkg_installed/%VCPKG_DEFAULT_TRIPLET% + set | sort > new.env + comm -13 old.env new.env >> %GITHUB_ENV% del *.env + + - name: baseruby version + run: ruby -v + + - name: compiler version + run: cl + + - name: volume info + run: Get-Volume + shell: pwsh + + # TODO: We should use `../src` instead of `D:/a/ruby/ruby/src` - name: Configure + run: >- + ../src/win32/configure.bat --disable-install-doc + --with-opt-dir=%RUBY_OPT_DIR% + --with-gmp + + - run: nmake prepare-vcpkg + + - run: nmake incs + + - run: nmake extract-extlibs + + # On all other platforms, test-spec depending on extract-gems (in common.mk) is enough. + # But not for this Visual Studio workflow. So here we extract gems before building. + - run: nmake extract-gems + + # windows-11-arm runner cannot run `ruby tool/file2lastrev.rb --revision.h --output=revision.h` + - name: make revision.h run: | - ../src/win32/configure.bat --disable-install-doc --enable-bundled-libffi --with-opt-dir=C:/vcpkg/installed/x64-windows --with-openssl-dir="C:/Program Files/OpenSSL-Win64" - - name: nmake - run: | - echo ^#^#[group]incs - nmake incs - echo ^#^#[endgroup] - echo ^#^#[group]extract-extlibs - nmake extract-extlibs - echo ^#^#[endgroup] - nmake - env: - YACC: win_bison - - name: nmake test - timeout-minutes: 5 - run: | - nmake test - - name: nmake test-all - timeout-minutes: 60 - run: | - nmake test-all TESTOPTS="-j%NUMBER_OF_PROCESSORS% --job-status=normal" - continue-on-error: ${{ matrix.continue-on-error || false }} - - name: nmake test-spec - timeout-minutes: 10 - run: | - nmake test-spec - continue-on-error: ${{ matrix.continue-on-error || false }} - - uses: k0kubun/action-slack@v2.0.0 + win32\lastrev.bat | win32\ifchange.bat --timestamp=.revision.time revision.h - + type revision.h + working-directory: src + + - run: nmake + + - name: Set up Launchable + uses: ./.github/actions/launchable/setup with: - payload: | - { - "ci": "GitHub Actions", - "env": "VS${{ matrix.vs }} / ${{ matrix.test_task || 'check' }}", - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", - "commit": "${{ github.sha }}", - "branch": "${{ github.ref }}".split('/').reverse()[0] - } + os: windows-${{ matrix.os }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + test-task: ${{ matrix.test_task || 'check' }} + continue-on-error: true + if: ${{ matrix.test_task != 'test-bundled-gems' }} + timeout-minutes: 3 + + - run: nmake ${{ matrix.test_task || 'check' }} env: + RUBY_TESTOPTS: -j${{ env.TEST_JOBS || 4 }} + timeout-minutes: 70 + + - uses: ./.github/actions/slack + with: + label: Windows ${{ matrix.os }} / VC ${{ matrix.vc }} / ${{ matrix.test_task || 'check' }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: windows-latest + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/wsl.yml b/.github/workflows/wsl.yml new file mode 100644 index 0000000000..640f18ce42 --- /dev/null +++ b/.github/workflows/wsl.yml @@ -0,0 +1,70 @@ +name: Ubuntu on WSL + +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +jobs: + wsl: + runs-on: windows-2025 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - name: Install or update WSL + uses: Ubuntu/WSL/.github/actions/wsl-install@main + with: + distro: Ubuntu-24.04 + + - name: Install dependencies + uses: Ubuntu/WSL/.github/actions/wsl-bash@main + with: + distro: Ubuntu-24.04 + working-dir: /tmp/github/ + exec: | + DEBIAN_FRONTEND=noninteractive sudo apt update + DEBIAN_FRONTEND=noninteractive sudo apt install -y ruby build-essential autoconf libssl-dev libyaml-dev zlib1g-dev libgmp-dev libffi-dev + + - name: Check out the repository + uses: Ubuntu/WSL/.github/actions/wsl-checkout@main + with: + distro: Ubuntu-24.04 + working-dir: /tmp/github/ + submodules: true + + - name: Build + uses: Ubuntu/WSL/.github/actions/wsl-bash@main + with: + distro: Ubuntu-24.04 + working-dir: /tmp/github/ + exec: | + ./autogen.sh + ./configure --disable-install-doc + make ruby -j4 + make extract-gems + make -j4 + + - name: Test + uses: Ubuntu/WSL/.github/actions/wsl-bash@main + with: + distro: Ubuntu-24.04 + working-dir: /tmp/github/ + exec: | + ./ruby -v + # make check TESTS="-j4" MSPECOPT="-j" diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml new file mode 100644 index 0000000000..a59b4d6508 --- /dev/null +++ b/.github/workflows/yjit-macos.yml @@ -0,0 +1,198 @@ +name: YJIT macOS +on: + push: + branches: + - master + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + types: + - opened + - synchronize + - reopened + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + cargo: + name: cargo test + + runs-on: macos-14 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - run: RUST_BACKTRACE=1 cargo test + working-directory: yjit + + # Also compile and test with all features enabled + - run: RUST_BACKTRACE=1 cargo test --all-features + working-directory: yjit + + # Check that we can build in release mode too + - run: cargo build --release + working-directory: yjit + + make: + strategy: + matrix: + include: + - test_task: 'check' + configure: '--enable-yjit' + yjit_opts: '--yjit' + - test_task: 'check' + configure: '--enable-yjit=dev' + yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc' + specopts: '-T --yjit-call-threshold=1 -T --yjit-verify-ctx -T --yjit-code-gc' + fail-fast: false + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUN_OPTS: ${{ matrix.yjit_opts }} + SPECOPTS: ${{ matrix.specopts }} + + runs-on: macos-14 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - name: Install libraries + uses: ./.github/actions/setup/macos + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: Run configure + run: ../src/configure -C --disable-install-doc ${{ matrix.configure }} + + - run: make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + + - run: make + + - name: Verify that --yjit-dump-disasm works + run: | + ./miniruby --yjit-call-threshold=1 --yjit-dump-disasm -e0 | \ + wc -l | \ + ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10' + if: ${{ contains(matrix.configure, 'jit=dev') }} + + - name: Set ENV for YJIT + run: | + echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV + echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV + + - name: Set test options for skipped tests + run: | + set -x + TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')" + echo "TESTS=${TESTS}" >> $GITHUB_ENV + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: macos-14 + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + is-yjit: true + continue-on-error: true + timeout-minutes: 3 + + - name: make ${{ matrix.test_task }} + run: | + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + set -x + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \ + RUN_OPTS="$RUN_OPTS" \ + SPECOPTS="$SPECOPTS" + timeout-minutes: 60 + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + SYNTAX_SUGGEST_TIMEOUT: '5' + PRECHECK_BUNDLED_GEMS: 'no' + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} + continue-on-error: ${{ matrix.continue-on-test_task || false }} + + - name: make skipped tests + run: | + make -s test-all TESTS="${TESTS//-n!\//-n/}" + env: + GNUMAKEFLAGS: '' + RUBY_TESTOPTS: '-v --tty=no' + PRECHECK_BUNDLED_GEMS: 'no' + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + + - name: Dump crash logs + if: ${{ failure() }} + continue-on-error: true + run: | + tail --verbose --lines=+1 rb_crash_*.txt + exit 1 + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.test_task }} ${{ matrix.configure }} ${{ matrix.yjit_opts }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: macos-14 + needs: [make] + steps: + - name: ${{ github.workflow }} jobs have failed + run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml new file mode 100644 index 0000000000..150f0b3275 --- /dev/null +++ b/.github/workflows/yjit-ubuntu.yml @@ -0,0 +1,240 @@ +name: YJIT Ubuntu +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + cargo: + name: cargo test + + # GitHub Action's image seems to already contain a Rust 1.58.0. + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + # For now we can't run cargo test --offline because it complains about the + # capstone dependency, even though the dependency is optional + #- run: cargo test --offline + + - run: RUST_BACKTRACE=1 cargo test + working-directory: yjit + + # Also compile and test with all features enabled + - run: RUST_BACKTRACE=1 cargo test --all-features + working-directory: yjit + + # Check that we can build in release mode too + - run: cargo build --release + working-directory: yjit + + lint: + name: cargo clippy + + # GitHub Action's image seems to already contain a Rust 1.58.0. + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + # Check that we don't have linting errors in release mode, too + - run: cargo clippy --all-targets --all-features + working-directory: yjit + + make: + strategy: + fail-fast: false + matrix: + include: + - test_task: 'yjit-bindgen' + hint: 'To fix: use patch in logs' + # Build with YJIT+ZJIT for output that works in the most number of configurations + configure: '--with-gcc=clang-14 --enable-yjit=dev --enable-zjit' + libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1' + + - test_task: 'check' + # YJIT should be automatically built in release mode on x86-64 Linux with rustc present + #configure: "--enable-yjit RUSTC='rustc +1.58.0'" + configure: "RUSTC='rustc +1.58.0'" + rust_version: '1.58.0' + + - test_task: 'check' + configure: '--enable-yjit=dev' + + - test_task: 'check' + configure: '--enable-yjit=dev' + yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc' + specopts: '-T --yjit-call-threshold=1 -T --yjit-verify-ctx -T --yjit-code-gc' + + - test_task: 'test-bundled-gems' + configure: '--enable-yjit=dev' + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUN_OPTS: ${{ matrix.yjit_opts }} + YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }} + SPECOPTS: ${{ matrix.specopts }} + RUBY_DEBUG: ci + RUST_BACKTRACE: 1 + + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/ubuntu + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.1' + bundler: none + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: Install Rust + if: ${{ matrix.rust_version }} + run: rustup install ${{ matrix.rust_version }} --profile minimal + + - name: Remove cargo + # Since this tests a `rustc` build for release, remove `cargo` to ensure + # that only `rustc` is used. + if: ${{ contains(matrix.configure, 'rustc') }} + run: sudo rm $(which -a cargo | uniq) + + - name: Run configure + run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }} + + - run: make incs + + - run: make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + + - run: make + + - name: Verify that --yjit-dump-disasm works + run: | + ./miniruby --yjit-call-threshold=1 --yjit-dump-disasm -e0 | \ + wc -l | \ + ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10' + if: ${{ contains(matrix.configure, 'jit=dev') }} + + - name: Set ENV for YJIT + run: | + echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV + echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV + + # Check that the binary was built with YJIT + - name: Check YJIT enabled + run: ./miniruby --yjit -v | grep "+YJIT" + + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: ubuntu-22.04 + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + is-yjit: true + continue-on-error: true + timeout-minutes: 3 + + - name: make ${{ matrix.test_task }} + run: | + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + set -x + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \ + RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS" \ + YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS" + timeout-minutes: 90 + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + PRECHECK_BUNDLED_GEMS: 'no' + SYNTAX_SUGGEST_TIMEOUT: '5' + YJIT_BINDGEN_DIFF_OPTS: '--exit-code' + LIBCLANG_PATH: ${{ matrix.libclang_path }} + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} + continue-on-error: ${{ matrix.continue-on-test_task || false }} + + - name: Dump crash logs + if: ${{ failure() }} + continue-on-error: true + run: | + tail --verbose --lines=+1 rb_crash_*.txt + exit 1 + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.test_task }} ${{ matrix.configure }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: ubuntu-latest + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml new file mode 100644 index 0000000000..a638907811 --- /dev/null +++ b/.github/workflows/zjit-macos.yml @@ -0,0 +1,214 @@ +name: ZJIT macOS +on: + push: + branches: + - master + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + types: + - opened + - synchronize + - reopened + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + fail-fast: false + matrix: + include: + - test_task: 'check' + run_opts: '--zjit-call-threshold=1' + specopts: '-T --zjit-call-threshold=1' + configure: '--enable-zjit=dev' + + - test_task: 'check' + run_opts: '--zjit-disable-hir-opt --zjit-call-threshold=1' + specopts: '-T --zjit-disable-hir-opt -T --zjit-call-threshold=1' + configure: '--enable-zjit=dev' + + - test_task: 'zjit-check' # zjit-test + quick feedback of test_zjit.rb + configure: '--enable-yjit=dev --enable-zjit' + rust_version: "1.85.0" + + - test_task: 'ruby' + hint: 'combo build test' + configure: '--enable-yjit --enable-zjit' + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUN_OPTS: ${{ matrix.run_opts }} + SPECOPTS: ${{ matrix.specopts }} + TESTOPTS: ${{ matrix.testopts }} + ZJIT_RB_BUG: 1 + + runs-on: macos-14 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - name: Install libraries + uses: ./.github/actions/setup/macos + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: Install Rust + if: ${{ matrix.rust_version }} + run: | + rustup install ${{ matrix.rust_version }} --profile minimal + rustup default ${{ matrix.rust_version }} + + - uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9 + if: ${{ matrix.test_task == 'zjit-check' }} + + - name: Run configure + run: ../src/configure -C --disable-install-doc ${{ matrix.configure }} + + - run: make + + - name: Verify that --zjit-dump-disasm works + run: | + ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e0 | \ + wc -l | \ + ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10' + if: ${{ contains(matrix.configure, 'jit=dev') }} + + - name: Set ENV for ZJIT + run: | + echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV + + - name: make ${{ matrix.test_task }} + run: | + set -x + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \ + RUN_OPTS="$RUN_OPTS" \ + SPECOPTS="$SPECOPTS" \ + TESTOPTS="$TESTOPTS" + timeout-minutes: 60 + env: + RUBY_TESTOPTS: '-q --tty=no' + EXCLUDES: '../src/test/.excludes-zjit' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + SYNTAX_SUGGEST_TIMEOUT: '5' + PRECHECK_BUNDLED_GEMS: 'no' + continue-on-error: ${{ matrix.continue-on-test_task || false }} + + - name: Dump crash logs + if: ${{ failure() }} + continue-on-error: true + run: | + tail --verbose --lines=+1 rb_crash_*.txt + exit 1 + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.test_task }} ${{ matrix.configure }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: macos-14 + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + + # Separated from `make` job to avoid making it a required status check for now + ruby-bench: + strategy: + matrix: + include: + # Test --call-threshold=2 with 2 iterations in total + - ruby_opts: '--zjit-call-threshold=2' + bench_opts: '--warmup=1 --bench=1 --excludes=lobsters' + configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow + + runs-on: macos-14 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: ./.github/actions/setup/macos + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + + - name: Run configure + run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install" ${{ matrix.configure }} + + - run: make install + + # setup/directories set MAKEFLAGS=-j4 for macOS, which randomly fails sqlite3.gem builds + - name: Unset MAKEFLAGS + run: echo "MAKEFLAGS=" >> "$GITHUB_ENV" + + - name: Checkout ruby-bench + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + repository: ruby/ruby-bench + path: ruby-bench + + # If you want to skip failing benchmark, consider using `--excludes`. + # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'` + - name: Run ruby-bench + run: ruby run_benchmarks.rb -e "zjit::../build/install/bin/ruby ${{ matrix.ruby_opts }}" ${{ matrix.bench_opts }} + working-directory: ruby-bench + + - uses: ./.github/actions/slack + with: + label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml new file mode 100644 index 0000000000..28bfec963e --- /dev/null +++ b/.github/workflows/zjit-ubuntu.yml @@ -0,0 +1,267 @@ +name: ZJIT Ubuntu +on: + push: + branches: + - master + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + types: + - opened + - synchronize + - reopened + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + lint: + name: cargo clippy + + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - run: cargo clippy --all-targets --all-features + working-directory: zjit + + make: + strategy: + fail-fast: false + matrix: + include: + - test_task: 'check' + run_opts: '--zjit-call-threshold=1' + specopts: '-T --zjit-call-threshold=1' + configure: '--enable-zjit=dev' + + - test_task: 'check' + run_opts: '--zjit-disable-hir-opt --zjit-call-threshold=1' + specopts: '-T --zjit-disable-hir-opt -T --zjit-call-threshold=1' + configure: '--enable-zjit=dev' + + # The optimizer benefits from at least 1 iteration of profiling. Also, many + # regression tests in bootstraptest/test_yjit.rb assume call-threshold=2. + - test_task: 'btest' + run_opts: '--zjit-call-threshold=2' + configure: '--enable-zjit=dev' + + - test_task: 'zjit-check' # zjit-test + quick feedback of test_zjit.rb + configure: '--enable-yjit --enable-zjit=dev' + rust_version: '1.85.0' + + - test_task: 'zjit-bindgen' + hint: 'To fix: use patch in logs' + # Build with YJIT+ZJIT for output that works in the most number of configurations + configure: '--enable-zjit=dev --enable-yjit --with-gcc=clang-16' + clang_path: '/usr/bin/clang-16' + runs-on: 'ubuntu-24.04' # for clang-16 + + - test_task: 'test-bundled-gems' + configure: '--enable-zjit=dev' + run_opts: '--zjit-call-threshold=1' + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUN_OPTS: ${{ matrix.run_opts }} + YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }} + SPECOPTS: ${{ matrix.specopts }} + TESTOPTS: ${{ matrix.testopts }} + RUBY_DEBUG: ci + BUNDLE_JOBS: 8 # for yjit-bench + RUST_BACKTRACE: 1 + ZJIT_RB_BUG: 1 + + runs-on: ${{ matrix.runs-on || 'ubuntu-22.04' }} + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/ubuntu + + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 + with: + ruby-version: '3.1' + bundler: none + + - uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9 + if: ${{ matrix.test_task == 'zjit-check' }} + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: Install Rust + if: ${{ matrix.rust_version }} + run: | + rustup install ${{ matrix.rust_version }} --profile minimal + rustup default ${{ matrix.rust_version }} + + - name: Install rustfmt + if: ${{ matrix.test_task == 'zjit-bindgen' }} + run: rustup component add rustfmt + + - name: Run configure + run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }} + + - run: make incs + + - run: make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + + - run: make + + - name: Verify that --zjit-dump-disasm works + run: | + ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e0 | \ + wc -l | \ + ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10' + if: ${{ contains(matrix.configure, 'jit=dev') }} + + # Check that the binary was built with ZJIT + - name: Check ZJIT enabled + run: ./miniruby --zjit -v | grep "+ZJIT" + if: ${{ matrix.configure != '--disable-zjit' }} + + - name: Set ENV for ZJIT + run: | + echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV + + - name: make ${{ matrix.test_task }} + run: | + set -x + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \ + RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS" \ + TESTOPTS="$TESTOPTS" \ + ZJIT_BINDGEN_DIFF_OPTS="$ZJIT_BINDGEN_DIFF_OPTS" + timeout-minutes: 90 + env: + RUBY_TESTOPTS: '-q --tty=no' + EXCLUDES: '../src/test/.excludes-zjit' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + PRECHECK_BUNDLED_GEMS: 'no' + SYNTAX_SUGGEST_TIMEOUT: '5' + ZJIT_BINDGEN_DIFF_OPTS: '--exit-code' + CLANG_PATH: ${{ matrix.clang_path }} + continue-on-error: ${{ matrix.continue-on-test_task || false }} + + - name: Dump crash logs + if: ${{ failure() }} + continue-on-error: true + run: | + tail --verbose --lines=+1 rb_crash_*.txt + exit 1 + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.test_task }} ${{ matrix.configure }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: ubuntu-22.04 + needs: [make] + steps: + - name: ${{ github.workflow }} jobs have failed + run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + + # Separated from `make` job to avoid making it a required status check for now + ruby-bench: + strategy: + matrix: + include: + # Test --call-threshold=2 with 2 iterations in total + - ruby_opts: '--zjit-call-threshold=2' + bench_opts: '--warmup=1 --bench=1 --excludes=lobsters' + configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow + + runs-on: ubuntu-24.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: ./.github/actions/setup/ubuntu + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + + - name: Run configure + run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install" ${{ matrix.configure }} + + - run: make install + + - name: Checkout ruby-bench + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + repository: ruby/ruby-bench + path: ruby-bench + + # If you want to skip failing benchmark, consider using `--excludes`. + # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'` + - name: Run ruby-bench + run: ruby run_benchmarks.rb -e "zjit::../build/install/bin/ruby ${{ matrix.ruby_opts }}" ${{ matrix.bench_opts }} + working-directory: ruby-bench + + - uses: ./.github/actions/slack + with: + label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + +defaults: + run: + working-directory: build diff --git a/.gitignore b/.gitignore index 8d11d7278a..6cf5fb5f32 100644 --- a/.gitignore +++ b/.gitignore @@ -10,20 +10,24 @@ *.dylib *.elc *.i +*.ii *.inc *.log *.o +*.o.tmp *.obj *.old *.orig *.pch *.pdb *.rbinc +*.rbbin *.rej *.s *.sav *.sl *.so +*.so.* *.swp *.yarb *~ @@ -47,6 +51,7 @@ y.tab.c *.gcno *.gcov *.vscode +!misc/.vscode lcov*.info # / @@ -120,29 +125,33 @@ lcov*.info /repack /revision.h /revision.tmp +/ripper.tmp.y /riscos /rubicon /ruby /ruby-runner /ruby-runner.h /ruby-man.rd.gz +/rubyspec_temp /run.gdb /sizes.c /static-ruby /test.rb /test-coverage.dat /tmp +/vcpkg_installed /transdb.h /uncommon.mk /verconf.h /verconf.mk /web -/yasmdata.rb # /bin/ /bin/*.exe /bin/*.dll +/bin/goruby +/bin/ruby # /benchmark/ /benchmark/bm_require.data @@ -158,6 +167,7 @@ lcov*.info # /coroutine/ !/coroutine/**/*.s +!/coroutine/**/*.S # /enc/trans/ /enc/trans/*.c @@ -182,6 +192,9 @@ lcov*.info /ext/-test-/win32/dln/dlntest.exp /ext/-test-/win32/dln/dlntest.lib +# /ext/-test-/gems +/ext/-test-/gems + # /ext/etc/ /ext/etc/constdefs.h @@ -194,8 +207,10 @@ lcov*.info # /ext/ripper/ /ext/ripper/eventids1.c +/ext/ripper/eventids1.h /ext/ripper/.eventids2-check /ext/ripper/eventids2table.c +/ext/ripper/ripper_init.c /ext/ripper/ripper.* /ext/ripper/ids1 /ext/ripper/ids2 @@ -214,7 +229,10 @@ lcov*.info /lib/ruby/[1-9]*.* /lib/ruby/vendor_ruby -# /spec/bundler +# /misc/ +/misc/**/__pycache__ + +# for `make test-bundler` /.rspec_status # /tool/ @@ -224,7 +242,39 @@ lcov*.info # /win32/ /win32/*.ico -# MJIT -/rb_mjit_header.h -/mjit_config.h -/include/ruby-*/*/rb_mjit_min_header-*.h + +# YJIT +/yjit-bench +/yjit_exit_locations.dump + +# Rust +/target + +# /wasm/ +/wasm/tests/*.wasm + +# prism +/lib/prism/compiler.rb +/lib/prism/dispatcher.rb +/lib/prism/dot_visitor.rb +/lib/prism/dsl.rb +/lib/prism/inspect_visitor.rb +/lib/prism/mutation_compiler.rb +/lib/prism/node.rb +/lib/prism/reflection.rb +/lib/prism/serialize.rb +/lib/prism/visitor.rb +/prism/api_node.c +/prism/ast.h +/prism/diagnostic.c +/prism/diagnostic.h +/prism/node.c +/prism/prettyprint.c +/prism/serialize.c +/prism/token_type.c +/prism/srcs.mk + +# tool/update-NEWS-gemlist.rb +/bundled_gems.json +/default_gems.json +/gems/default_gems diff --git a/.indent.pro b/.indent.pro new file mode 100644 index 0000000000..1d61cbcad1 --- /dev/null +++ b/.indent.pro @@ -0,0 +1,32 @@ +-bap +-nbbb +-nbc +-br +-brs +-nbs +-ncdb +-nce +-cdw +-cli2 +-cbi2 +-ndj +-ncs +-nfc1 +-i4 +-l120 +-lp +-npcs +-psl +-sc +-sob +-sbi4 +-nut +-par + +-TID +-TVALUE +-Tst_data_t +-Tst_index_t +-Tst_table +-Trb_data_type_t +-TFILE diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000..213a0f4916 --- /dev/null +++ b/.mailmap @@ -0,0 +1,431 @@ +git[bot] <svn-admin@ruby-lang.org> +git[bot] <svn-admin@ruby-lang.org> git <svn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> +svn[bot] <svn-admin@ruby-lang.org> svn <svn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# a_matsuda +Akira Matsuda <ronnie@dio.jp> +Akira Matsuda <ronnie@dio.jp> <a_matsuda@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# aamine +Minero Aoki <aamine@loveruby.net> +Minero Aoki <aamine@loveruby.net> <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# akira +akira yamada <akira@ruby-lang.org> +## akira yamada <akira@ruby-lang.org> <akira@rice.p.arika.org> +akira yamada <akira@ruby-lang.org> <akira@arika.org> +akira yamada <akira@ruby-lang.org> <akira@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# akiyoshi +AKIYOSHI, Masamichi <masamichi.akiyoshi@hp.com> +AKIYOSHI, Masamichi <masamichi.akiyoshi@hp.com> <akiyoshi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# akr +Tanaka Akira <akr@fsij.org> +Tanaka Akira <akr@fsij.org> <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# arai +Koji Arai <jca02266@nifty.ne.jp> +Koji Arai <jca02266@nifty.ne.jp> <arai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# arton +Akio Tajima <artonx@yahoo.co.jp> +Akio Tajima <artonx@yahoo.co.jp> <arton@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# aycabta +aycabta <aycabta@gmail.com> +aycabta <aycabta@gmail.com> <aycabta@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ayumin +Ayumu AIZAWA <ayumu.aizawa@gmail.com> +Ayumu AIZAWA <ayumu.aizawa@gmail.com> <ayumin@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# azav +Alexander Zavorine <alexandre.zavorine@nokia.com> +Alexander Zavorine <alexandre.zavorine@nokia.com> <azav@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# charliesome +Charlie Somerville <charliesome@ruby-lang.org> +Charlie Somerville <charliesome@ruby-lang.org> <charliesome@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# dave +Dave Thomas <dave@pragprog.com> +Dave Thomas <dave@pragprog.com> <dave@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# davidflanagan +David Flanagan <davidflanagan@ruby-lang.org> +David Flanagan <davidflanagan@ruby-lang.org> <david@think32> +David Flanagan <davidflanagan@ruby-lang.org> <david@davidflanagan.com> +David Flanagan <davidflanagan@ruby-lang.org> <davidflanagan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# dblack +David A. Black <dblack@rubypal.com> +David A. Black <dblack@rubypal.com> <dblack@wobblini.net> +David A. Black <dblack@rubypal.com> <dblack@superlink.net> +David A. Black <dblack@rubypal.com> <dblack@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# drbrain +Eric Hodel <drbrain@segment7.net> +Eric Hodel <drbrain@segment7.net> <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# duerst +Martin Dürst <duerst@it.aoyama.ac.jp> +Martin Dürst <duerst@it.aoyama.ac.jp> <duerst@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# eban +WATANABE Hirofumi <eban@ruby-lang.org> +WATANABE Hirofumi <eban@ruby-lang.org> <eban@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# emboss +Martin Bosslet <Martin.Bosslet@gmail.com> +Martin Bosslet <Martin.Bosslet@gmail.com> <Martin.Bosslet@googlemail.com> +Martin Bosslet <Martin.Bosslet@gmail.com> <emboss@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# eregon +Benoit Daloze <eregontp@gmail.com> +Benoit Daloze <eregontp@gmail.com> <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# evan +Evan Phoenix <evan@ruby-lang.org> +Evan Phoenix <evan@ruby-lang.org> <evan@fallingsnow.net> +Evan Phoenix <evan@ruby-lang.org> <evan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# glass +Masaki Matsushita <glass.saga@gmail.com> +Masaki Matsushita <glass.saga@gmail.com> <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# gogotanaka +Kazuki Tanaka <gogotanaka@ruby-lang.org> +Kazuki Tanaka <gogotanaka@ruby-lang.org> <gogotanaka@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# gotoken +Kentaro Goto <gotoken@gmail.com> +Kentaro Goto <gotoken@gmail.com> <gotoken@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# gotoyuzo +GOTOU Yuuzou <gotoyuzo@notwork.org> +GOTOU Yuuzou <gotoyuzo@notwork.org> <gotoyuzo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# gsinclair +Gavin Sinclair <gsinclair@soyabean.com.au> +Gavin Sinclair <gsinclair@soyabean.com.au> <gsinclair@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# H_Konishi +KONISHI Hiromasa <konishih@fd6.so-net.ne.jp> +KONISHI Hiromasa <konishih@fd6.so-net.ne.jp> <H_Konishi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# headius +Charles Oliver Nutter <headius@headius.com> +Charles Oliver Nutter <headius@headius.com> <headius@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# hone +Terence Lee <hone@heroku.com> +Terence Lee <hone@heroku.com> <hone@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# hsbt +Hiroshi SHIBATA <hsbt@ruby-lang.org> +Hiroshi SHIBATA <hsbt@ruby-lang.org> <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# iwamatsu +Nobuhiro Iwamatsu <iwamatsu@nigauri.org> +Nobuhiro Iwamatsu <iwamatsu@nigauri.org> <iwamatsu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# jeg2 +James Edward Gray II <james@graysoftinc.com> +James Edward Gray II <james@graysoftinc.com> <jeg2@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# jim +Jim Weirich <jim@tardis.local> +Jim Weirich <jim@tardis.local> <jim@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# k0kubun +Takashi Kokubun <takashikkbn@gmail.com> +Takashi Kokubun <takashikkbn@gmail.com> <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# kanemoto +Yutaka Kanemoto <kanemoto@ruby-lang.org> +Yutaka Kanemoto <kanemoto@ruby-lang.org> <kanemoto@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# katsu +UENO Katsuhiro <katsu@blue.sky.or.jp> +UENO Katsuhiro <katsu@blue.sky.or.jp> <katsu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# kazu +Kazuhiro NISHIYAMA <zn@mbf.nifty.com> +Kazuhiro NISHIYAMA <zn@mbf.nifty.com> <kazu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# keiju +Keiju Ishitsuka <keiju@ishitsuka.com> +Keiju Ishitsuka <keiju@ishitsuka.com> <keiju@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# knu +Akinori MUSHA <knu@iDaemons.org> +Akinori MUSHA <knu@iDaemons.org> <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ko1 +Koichi Sasada <ko1@atdot.net> +Koichi Sasada <ko1@atdot.net> <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# kosaki +KOSAKI Motohiro <kosaki.motohiro@gmail.com> +KOSAKI Motohiro <kosaki.motohiro@gmail.com> <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# kosako +K.Kosako <sndgk393@ybb.ne.jp> +K.Kosako <sndgk393@ybb.ne.jp> <kosako@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# kou +Sutou Kouhei <kou@clear-code.com> +Sutou Kouhei <kou@clear-code.com> <kou@cozmixng.org> +Sutou Kouhei <kou@clear-code.com> <kou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# kouji +Kouji Takao <kouji.takao@gmail.com> +Kouji Takao <kouji.takao@gmail.com> <kouji@takao7.net> +Kouji Takao <kouji.takao@gmail.com> <kouji@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ksaito +Kazuo Saito <ksaito@uranus.dti.ne.jp> +Kazuo Saito <ksaito@uranus.dti.ne.jp> <ksaito@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ktsj +Kazuki Tsujimoto <kazuki@callcc.net> +Kazuki Tsujimoto <kazuki@callcc.net> <ktsj@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# luislavena +Luis Lavena <luislavena@gmail.com> +Luis Lavena <luislavena@gmail.com> <luislavena@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# mame +Yusuke Endoh <mame@ruby-lang.org> +## Yusuke Endoh <mame@ruby-lang.org> <mame@tsg.ne.jp> +Yusuke Endoh <mame@ruby-lang.org> <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# marcandre +Marc-Andre Lafortune <github@marc-andre.ca> +Marc-Andre Lafortune <ruby-core@marc-andre.ca> +Marc-Andre Lafortune <ruby-core@marc-andre.ca> <marcandre@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# matz +Yukihiro "Matz" Matsumoto <matz@ruby.or.jp> +Yukihiro "Matz" Matsumoto <matz@ruby.or.jp> <matz@ruby-lang.org> +Yukihiro "Matz" Matsumoto <matz@ruby.or.jp> <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# michal +Michal Rokos <michal@ruby-lang.org> +Michal Rokos <michal@ruby-lang.org> <michal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# mneumann +Michael Neumann <mneumann@ruby-lang.org> +Michael Neumann <mneumann@ruby-lang.org> <mneumann@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# mrkn +Kenta Murata <mrkn@mrkn.jp> +Kenta Murata <mrkn@mrkn.jp> <muraken@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> +Kenta Murata <mrkn@mrkn.jp> <3959+mrkn@users.noreply.github.com> +Kenta Murata <mrkn@mrkn.jp> <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# nagachika +nagachika <nagachika@ruby-lang.org> +nagachika <nagachika@ruby-lang.org> <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# nagai +Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> +Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# nahi +Hiroshi Nakamura <nahi@ruby-lang.org> +Hiroshi Nakamura <nahi@ruby-lang.org> <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# nari +Narihiro Nakamura <authornari@gmail.com> +Narihiro Nakamura <authornari@gmail.com> <nari@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# naruse +NARUSE, Yui <naruse@airemix.jp> +NARUSE, Yui <naruse@airemix.jp> <naruse@ruby-lang.org> +NARUSE, Yui <naruse@airemix.jp> <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ngoto +Naohisa Goto <ngotogenome@gmail.com> +Naohisa Goto <ngotogenome@gmail.com> <ngoto@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# nobu +Nobuyoshi Nakada <nobu@ruby-lang.org> +Nobuyoshi Nakada <nobu@ruby-lang.org> <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# normal +Eric Wong <normal@ruby-lang.org> +Eric Wong <normal@ruby-lang.org> <e@80x24.org> +Eric Wong <normal@ruby-lang.org> <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ntalbott +Nathaniel Talbott <ntalbott@ruby-lang.org> +Nathaniel Talbott <ntalbott@ruby-lang.org> <ntalbott@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ocean +Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp> +Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp> <ocean@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# odaira +Rei Odaira <rodaira@us.ibm.com> +Rei Odaira <rodaira@us.ibm.com> <Rei.Odaira@gmail.com> +Rei Odaira <rodaira@us.ibm.com> <odaira@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# okkez +okkez <okkez000@gmail.com> +okkez <okkez000@gmail.com> <okkez@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# rhe +Kazuki Yamaguchi <k@rhe.jp> +Kazuki Yamaguchi <k@rhe.jp> <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ryan +Ryan Davis <ryand-github@zenspider.com> +Ryan Davis <ryand-github@zenspider.com> <ryand-ruby@zenspider.com> +Ryan Davis <ryand-github@zenspider.com> <ryan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# samuel +Samuel Williams <samuel.williams@oriontransfer.co.nz> +Samuel Williams <samuel.williams@oriontransfer.co.nz> <samuel@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# seki +Masatoshi SEKI <m_seki@mva.biglobe.ne.jp> +Masatoshi SEKI <m_seki@mva.biglobe.ne.jp> <seki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ser +Sean Russell <ser@germane-software.com> +Sean Russell <ser@germane-software.com> <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# shigek +Shigeo Kobayashi <shigek@ruby-lang.org> +Shigeo Kobayashi <shigek@ruby-lang.org> <shigek@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# shirosaki +Hiroshi Shirosaki <h.shirosaki@gmail.com> +Hiroshi Shirosaki <h.shirosaki@gmail.com> <shirosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# sho-h +Sho Hashimoto <sho-h@ruby-lang.org> +Sho Hashimoto <sho-h@ruby-lang.org> <sho-h@netlab.jp> +Sho Hashimoto <sho-h@ruby-lang.org> <sho.hsmt@gmail.com> +Sho Hashimoto <sho-h@ruby-lang.org> <sho-h@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# shugo +Shugo Maeda <shugo@ruby-lang.org> +Shugo Maeda <shugo@ruby-lang.org> <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# shyouhei +卜部昌平 <shyouhei@ruby-lang.org> +卜部昌平 <shyouhei@ruby-lang.org> <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# siena +Siena. <siena@faculty.chiba-u.jp> +Siena. <siena@faculty.chiba-u.jp> <siena@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# sonots +sonots <sonots@gmail.com> +sonots <sonots@gmail.com> <sonots@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# sorah +Sorah Fukumori <her@sorah.jp> +Sorah Fukumori <her@sorah.jp> <sorah@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# stomar +Marcus Stollsteimer <sto.mar@web.de> +Marcus Stollsteimer <sto.mar@web.de> <stomar@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# suke +Masaki Suketa <masaki.suketa@nifty.ne.jp> +Masaki Suketa <masaki.suketa@nifty.ne.jp> <suke@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# tadd +Tadashi Saito <tad.a.digger@gmail.com> +Tadashi Saito <tad.a.digger@gmail.com> <tadd@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# tadf +Tadayoshi Funaba <tadf@dotrb.org> +Tadayoshi Funaba <tadf@dotrb.org> <tadf@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# takano32 +TAKANO Mitsuhiro <takano32@gmail.com> +TAKANO Mitsuhiro <takano32@gmail.com> <takano32@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# tarui +Masaya Tarui <tarui@ruby-lang.org> +Masaya Tarui <tarui@ruby-lang.org> <tarui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# technorama +Technorama Ltd. <oss-ruby@technorama.net> +Technorama Ltd. <oss-ruby@technorama.net> <technorama@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# tenderlove +Aaron Patterson <tenderlove@ruby-lang.org> +Aaron Patterson <tenderlove@ruby-lang.org> <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# tmm1 +Aman Gupta <ruby@tmm1.net> +Aman Gupta <ruby@tmm1.net> <tmm1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ts +Guy Decoux <ts@moulon.inra.fr> +Guy Decoux <ts@moulon.inra.fr> <ts@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# ttate +Takaaki Tateishi <ttate@ttsky.net> +## Takaaki Tateishi <ttate@ttsky.net> <ttate@kt.jaist.ac.jp> +Takaaki Tateishi <ttate@ttsky.net> <ttate@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# uema2 +Takaaki Uematsu <uema2x@jcom.home.ne.jp> +Takaaki Uematsu <uema2x@jcom.home.ne.jp> <uema2@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# usa +U.Nakamura <usa@ruby-lang.org> +U.Nakamura <usa@ruby-lang.org> <usa@garbagecollect.jp> +U.Nakamura <usa@ruby-lang.org> <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# wakou +Wakou Aoyama <wakou@ruby-lang.org> +Wakou Aoyama <wakou@ruby-lang.org> <wakou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# wanabe +wanabe <s.wanabe@gmail.com> +wanabe <s.wanabe@gmail.com> <wanabe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# watson1978 +Watson <watson1978@gmail.com> +Watson <watson1978@gmail.com> <watson1978@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# wew +William Webber <william@williamwebber.com> +William Webber <william@williamwebber.com> <wew@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# why +why the lucky stiff <why@ruby-lang.org> +why the lucky stiff <why@ruby-lang.org> <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# xibbar +Takeyuki FUJIOKA <xibbar@ruby-lang.org> +Takeyuki FUJIOKA <xibbar@ruby-lang.org> <xibbar@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# yugui +Yuki Yugui Sonoda <yugui@yugui.jp> +Yuki Yugui Sonoda <yugui@yugui.jp> <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# yui-knk +yui-knk <spiketeika@gmail.com> +yui-knk <spiketeika@gmail.com> <yui-knk@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# yuki +Yuki Nishijima <yuki24@hey.com> +Yuki Nishijima <yuki24@hey.com> <mail@yukinishijima.net> +Yuki Nishijima <yuki24@hey.com> <yuki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# zsombor +Dee Zsombor <zsombor@ruby-lang.org> +Dee Zsombor <zsombor@ruby-lang.org> <zsombor@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> + +# zzak +zzak <zzakscott@gmail.com> +zzak <zzakscott@gmail.com> <zzak@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> diff --git a/.rdoc_options b/.rdoc_options new file mode 100644 index 0000000000..89265cafd4 --- /dev/null +++ b/.rdoc_options |