# AUTOGENERATED DEPENDENCIES START pathname.o: $(RUBY_EXTCONF_H) pathname.o: $(arch_hdrdir)/ruby/config.h pathname.o: $(hdrdir)/ruby.h pathname.o: $(hdrdir)/ruby/internal/anyargs.h pathname.o: $(hdrdir)/ruby/internal/arithmetic.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/char.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/double.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/int.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/long.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/short.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h pathname.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h pathname.o: $(hdrdir)/ruby/internal/assume.h pathname.o: $(hdrdir)/ruby/internal/attr/alloc_size.h pathname.o: $(hdrdir)/ruby/internal/attr/artificial.h pathname.o: $(hdrdir)/ruby/internal/attr/cold.h pathname.o: $(hdrdir)/ruby/internal/attr/const.h pathname.o: $(hdrdir)/ruby/internal/attr/constexpr.h pathname.o: $(hdrdir)/ruby/internal/attr/deprecated.h pathname.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h pathname.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h pathname.o: $(hdrdir)/ruby/internal/attr/error.h pathname.o: $(hdrdir)/ruby/internal/attr/flag_enum.h pathname.o: $(hdrdir)/ruby/internal/attr/forceinline.h pathname.o: $(hdrdir)/ruby/internal/attr/format.h pathname.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h pathname.o: $(hdrdir)/ruby/internal/attr/noalias.h pathname.o: $(hdrdir)/ruby/internal/attr/nodiscard.h pathname.o: $(hdrdir)/ruby/internal/attr/noexcept.h pathname.o: $(hdrdir)/ruby/internal/attr/noinline.h pathname.o: $(hdrdir)/ruby/internal/attr/nonnull.h pathname.o: $(hdrdir)/ruby/internal/attr/noreturn.h pathname.o: $(hdrdir)/ruby/internal/attr/pure.h pathname.o: $(hdrdir)/ruby/internal/attr/restrict.h pathname.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h pathname.o: $(hdrdir)/ruby/internal/attr/warning.h pathname.o: $(hdrdir)/ruby/internal/attr/weakref.h pathname.o: $(hdrdir)/ruby/internal/cast.h pathname.o: $(hdrdir)/ruby/internal/compiler_is.h pathname.o: $(hdrdir)/ruby/internal/compiler_is/apple.h pathname.o: $(hdrdir)/ruby/internal/compiler_is/clang.h pathname.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h pathname.o: $(hdrdir)/ruby/internal/compiler_is/intel.h pathname.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h pathname.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h pathname.o: $(hdrdir)/ruby/internal/compiler_since.h pathname.o: $(hdrdir)/ruby/internal/config.h pathname.o: $(hdrdir)/ruby/internal/constant_p.h pathname.o: $(hdrdir)/ruby/internal/core.h pathname.o: $(hdrdir)/ruby/internal/core/rarray.h pathname.o: $(hdrdir)/ruby/internal/core/rbasic.h pathname.o: $(hdrdir)/ruby/internal/core/rbignum.h pathname.o: $(hdrdir)/ruby/internal/core/rclass.h pathname.o: $(hdrdir)/ruby/internal/core/rdata.h pathname.o: $(hdrdir)/ruby/internal/core/rfile.h pathname.o: $(hdrdir)/ruby/internal/core/rhash.h pathname.o: $(hdrdir)/ruby/internal/core/robject.h pathname.o: $(hdrdir)/ruby/internal/core/rregexp.h pathname.o: $(hdrdir)/ruby/internal/core/rstring.h pathname.o: $(hdrdir)/ruby/internal/core/rstruct.h pathname.o: $(hdrdir)/ruby/internal/core/rtypeddata.h pathname.o: $(hdrdir)/ruby/internal/ctype.h pathname.o: $(hdrdir)/ruby/internal/dllexport.h pathname.o: $(hdrdir)/ruby/internal/dosish.h pathname.o: $(hdrdir)/ruby/internal/error.h pathname.o: $(hdrdir)/ruby/internal/eval.h pathname.o: $(hdrdir)/ruby/internal/event.h pathname.o: $(hdrdir)/ruby/internal/fl_type.h pathname.o: $(hdrdir)/ruby/internal/gc.h pathname.o: $(hdrdir)/ruby/internal/glob.h pathname.o: $(hdrdir)/ruby/internal/globals.h pathname.o: $(hdrdir)/ruby/internal/has/attribute.h pathname.o: $(hdrdir)/ruby/internal/has/builtin.h pathname.o: $(hdrdir)/ruby/internal/has/c_attribute.h pathname.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h pathname.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h pathname.o: $(hdrdir)/ruby/internal/has/extension.h pathname.o: $(hdrdir)/ruby/internal/has/feature.h pathname.o: $(hdrdir)/ruby/internal/has/warning.h pathname.o: $(hdrdir)/ruby/internal/intern/array.h pathname.o: $(hdrdir)/ruby/internal/intern/bignum.h pathname.o: $(hdrdir)/ruby/internal/intern/class.h pathname.o: $(hdrdir)/ruby/internal/intern/compar.h pathname.o: $(hdrdir)/ruby/internal/intern/complex.h pathname.o: $(hdrdir)/ruby/internal/intern/cont.h pathname.o: $(hdrdir)/ruby/internal/intern/dir.h pathname.o: $(hdrdir)/ruby/internal/intern/enum.h pathname.o: $(hdrdir)/ruby/internal/intern/enumerator.h pathname.o: $(hdrdir)/ruby/internal/intern/error.h pathname.o: $(hdrdir)/ruby/internal/intern/eval.h pathname.o: $(hdrdir)/ruby/internal/intern/file.h pathname.o: $(hdrdir)/ruby/internal/intern/gc.h pathname.o: $(hdrdir)/ruby/internal/intern/hash.h pathname.o: $(hdrdir)/ruby/internal/intern/io.h pathname.o: $(hdrdir)/ruby/internal/intern/load.h pathname.o: $(hdrdir)/ruby/internal/intern/marshal.h pathname.o: $(hdrdir)/ruby/internal/intern/numeric.h pathname.o: $(hdrdir)/ruby/internal/intern/object.h pathname.o: $(hdrdir)/ruby/internal/intern/parse.h pathname.o: $(hdrdir)/ruby/internal/intern/proc.h pathname.o: $(hdrdir)/ruby/internal/intern/process.h pathname.o: $(hdrdir)/ruby/internal/intern/random.h pathname.o: $(hdrdir)/ruby/internal/intern/range.h pathname.o: $(hdrdir)/ruby/internal/intern/rational.h pathname.o: $(hdrdir)/ruby/internal/intern/re.h pathname.o: $(hdrdir)/ruby/internal/intern/ruby.h pathname.o: $(hdrdir)/ruby/internal/intern/select.h pathname.o: $(hdrdir)/ruby/internal/intern/select/largesize.h pathname.o: $(hdrdir)/ruby/internal/intern/signal.h pathname.o: $(hdrdir)/ruby/internal/intern/sprintf.h pathname.o: $(hdrdir)/ruby/internal/intern/string.h pathname.o: $(hdrdir)/ruby/internal/intern/struct.h pathname.o: $(hdrdir)/ruby/internal/intern/thread.h pathname.o: $(hdrdir)/ruby/internal/intern/time.h pathname.o: $(hdrdir)/ruby/internal/intern/variable.h pathname.o: $(hdrdir)/ruby/internal/intern/vm.h pathname.o: $(hdrdir)/ruby/internal/interpreter.h pathname.o: $(hdrdir)/ruby/internal/iterator.h pathname.o: $(hdrdir)/ruby/internal/memory.h pathname.o: $(hdrdir)/ruby/internal/method.h pathname.o: $(hdrdir)/ruby/internal/module.h pathname.o: $(hdrdir)/ruby/internal/newobj.h pathname.o: $(hdrdir)/ruby/internal/rgengc.h pathname.o: $(hdrdir)/ruby/internal/scan_args.h pathname.o: $(hdrdir)/ruby/internal/special_consts.h pathname.o: $(hdrdir)/ruby/internal/static_assert.h pathname.o: $(hdrdir)/ruby/internal/stdalign.h pathname.o: $(hdrdir)/ruby/internal/stdbool.h pathname.o: $(hdrdir)/ruby/internal/symbol.h pathname.o: $(hdrdir)/ruby/internal/token_paste.h pathname.o: $(hdrdir)/ruby/internal/value.h pathname.o: $(hdrdir)/ruby/internal/value_type.h pathname.o: $(hdrdir)/ruby/internal/variable.h pathname.o: $(hdrdir)/ruby/internal/warning_push.h pathname.o: $(hdrdir)/ruby/internal/xmalloc.h pathname.o: $(hdrdir)/ruby/assert.h pathname.o: $(hdrdir)/ruby/backward.h pathname.o: $(hdrdir)/ruby/backward/2/assume.h pathname.o: $(hdrdir)/ruby/backward/2/attributes.h pathname.o: $(hdrdir)/ruby/backward/2/bool.h pathname.o: $(hdrdir)/ruby/backward/2/extern.h pathname.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h pathname.o: $(hdrdir)/ruby/backward/2/inttypes.h pathname.o: $(hdrdir)/ruby/backward/2/limits.h pathname.o: $(hdrdir)/ruby/backward/2/long_long.h pathname.o: $(hdrdir)/ruby/backward/2/r_cast.h pathname.o: $(hdrdir)/ruby/backward/2/rmodule.h pathname.o: $(hdrdir)/ruby/backward/2/stdalign.h pathname.o: $(hdrdir)/ruby/backward/2/stdarg.h pathname.o: $(hdrdir)/ruby/defines.h pathname.o: $(hdrdir)/ruby/encoding.h pathname.o: $(hdrdir)/ruby/intern.h pathname.o: $(hdrdir)/ruby/missing.h pathname.o: $(hdrdir)/ruby/onigmo.h pathname.o: $(hdrdir)/ruby/oniguruma.h pathname.o: $(hdrdir)/ruby/ruby.h pathname.o: $(hdrdir)/ruby/st.h pathname.o: $(hdrdir)/ruby/subst.h pathname.o: pathname.c # AUTOGENERATED DEPENDENCIES END p/macos/action.yml
@@ -19,10 +19,10 @@ hash.rb io.rb kernel.rb marshal.rb -rjit.rb numeric.rb nilclass.rb pack.rb +pathname_builtin.rb ractor.rb string.rb symbol.rb @@ -31,6 +31,7 @@ thread_sync.rb trace_point.rb warning.rb yjit.rb +zjit.rb # Errno::* known_errors.inc @@ -1,21 +1,7 @@ -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 @@ -65,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) @ (rb_shape_get_shape($arg0)->capacity) + 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 @@ -97,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.embed.ary) @ $len set print address on printf " len:%ld ", $len if $flags & RUBY_FL_USER6 @@ -155,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)) ? \ @@ -199,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 @@ -438,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.embed.ary) @ $len else output "" end @@ -452,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.embed.ary) @ $len end end @@ -541,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 RCLASS_ORIGIN((struct RClass *)($arg0)) != $arg0 - printf " -> %p", RCLASS_ORIGIN((struct RClass *)($arg0)) + 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 *RCLASS_EXT((struct RClass *)($arg0)) + print/x *$class_and_classext end document rp_class Print the content of a Class/Module. @@ -914,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 @@ -1124,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 @@ -1309,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" diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 60721014f7..d98646febf 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -9,6 +9,8 @@ c5e9af9c9d890578182a21e7b71b50334cd5579e e63a2115f64433b21cb5dd67c5bf8b30f87ef293 712ac99e4d0384a941c80a9f48f62943ba7d97c0 d1474affa8e105bece209cc9d594bb0a989859e1 +2da92388b948821269b18d6b178a680f17e41750 +5062c0c621d887367af8a054e5e5d83d7ec57dd3 # Enable Style/StringLiterals cop for RubyGems/Bundler d7ffd3fea402239b16833cc434404a7af82d44f3 @@ -33,3 +35,7 @@ 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 index aa23365e49..ab5b56a889 100644 --- a/.github/actions/compilers/action.yml +++ b/.github/actions/compilers/action.yml @@ -5,7 +5,7 @@ description: >- inputs: tag: required: false - default: clang-18 + default: clang-20 description: >- container image tag to use in this run. @@ -60,11 +60,17 @@ inputs: description: >- Whether to run `make check` - mspecopt: + test_all: required: false default: '' description: >- - Additional options for mspec. + 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 @@ -77,6 +83,16 @@ runs: - 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: >- @@ -95,7 +111,23 @@ runs: --env INPUT_CPPFLAGS='${{ inputs.cppflags }}' --env INPUT_APPEND_CONFIGURE='${{ inputs.append_configure }}' --env INPUT_CHECK='${{ inputs.check }}' - --env INPUT_MSPECOPT='${{ inputs.mspecopt }}' + --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 index 198ac0e174..b554151091 100755 --- a/.github/actions/compilers/entrypoint.sh +++ b/.github/actions/compilers/entrypoint.sh @@ -26,7 +26,7 @@ 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 --all)))" +export GNUMAKEFLAGS="-j$((1 + $(nproc)))" case "x${INPUT_ENABLE_SHARED}" in x | xno | xfalse ) @@ -39,12 +39,15 @@ 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}" \ @@ -68,29 +71,20 @@ if [[ -n "${INPUT_STATIC_EXTS}" ]]; then echo "::endgroup::" fi -pushd ${builddir} +if [ -n "$INPUT_TEST_ALL" ]; then + tests=" -- $INPUT_TEST_ALL" +else + tests=" -- ruby -ext-" +fi -case "${INPUT_APPEND_CONFIGURE}" in -*--with-shared-gc*) - export RUBY_GC_LIBRARY='librubygc.default.so' - mkdir -p /home/runner/shared-gc - grouped make shared-gc SHARED_GC=default - ;; -esac +pushd ${builddir} grouped make showflags grouped make all -grouped make test - -[[ -z "${INPUT_CHECK}" ]] && exit 0 - -if [ "$INPUT_CHECK" = "true" ]; then - tests="ruby -ext-" -else - tests="$INPUT_CHECK" -fi +# grouped make install -grouped make install -grouped make test-tool -grouped make test-all TESTS="-- $tests" -grouped env CHECK_LEAKS=true make test-spec MSPECOPT="$INPUT_MSPECOPT" +# 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 index 4b469ccd64..16af8fc3fd 100644 --- a/.github/actions/launchable/setup/action.yml +++ b/.github/actions/launchable/setup/action.yml @@ -3,11 +3,6 @@ description: >- Install the required dependencies and execute the necessary Launchable commands for test recording inputs: - report-path: - default: launchable_reports.json - required: true - description: The file path of the test report for uploading to Launchable - os: required: true description: The operating system that CI runs on. This value is used in Launchable flavor. @@ -35,21 +30,41 @@ inputs: required: false default: ${{ github.workspace }} description: >- - Directory to (re-)checkout source codes. Launchable retrives the commit information + Directory to (re-)checkout source codes. Launchable retrieves the commit information from the directory. - launchable-workspace: - required: true - default: ${{ github.event.repository.name }} - description: >- - A workspace name in Launchable - test-task: - required: true + required: false default: ${{ matrix.test_task }} description: >- - A test task that determine which tests are executed. + 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 @@ -61,11 +76,14 @@ runs: 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') + (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. @@ -74,13 +92,54 @@ runs: uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0 with: python-version: "3.x" - if: steps.enable-launchable.outputs.enable-launchable + 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 @@ -92,10 +151,13 @@ runs: : # 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=${{ inputs.launchable-workspace }}" >> $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 @@ -104,62 +166,148 @@ runs: # 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') + 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 - launchable verify || true : # 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. - : # - : # FIXME: Need to fix `WARNING: Failed to process a change to a file`. - : # https://github.com/launchableinc/cli/issues/786 - launchable record build --name ${github_ref}_${GITHUB_PR_HEAD_SHA} - echo "TESTS=${TESTS} --launchable-test-reports=${{ inputs.report-path }}" >> $GITHUB_ENV - if: steps.enable-launchable.outputs.enable-launchable - - - name: Variables to report Launchable - id: variables - shell: bash - run: | - set -x - : # flavor + build_name="${github_ref}_${GITHUB_PR_HEAD_SHA}" test_opts="${{ inputs.test-opts }}" test_opts="${test_opts// /}" test_opts="${test_opts//=/:}" - echo test-opts="$test_opts" >> $GITHUB_OUTPUT - : # report-path from srcdir - if [ "${srcdir}" = "${{ github.workspace }}" ]; then - dir= - else - # srcdir must be equal to or under workspace - dir=$(echo ${srcdir:+${srcdir}/} | sed 's:[^/][^/]*/:../:g') + 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 - report_path="${dir}${builddir:+${builddir}/}${report_path}" - echo report-path="${report_path}" >> $GITHUB_OUTPUT + 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: - srcdir: ${{ inputs.srcdir }} - builddir: ${{ inputs.builddir }} - report_path: ${{ inputs.report-path }} + 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.srcdir }} + working-directory: ${{ inputs.builddir }} post: | - : # record - launchable record tests --flavor os=${{ inputs.os }} --flavor test_task=${{ inputs.test-task }} --flavor test_opts=${test_opts} raw ${report_path} - rm -f ${report_path} - if: ${{ always() && steps.enable-launchable.outputs.enable-launchable }} + 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_opts: ${{ steps.variables.outputs.test-opts }} - report_path: ${{ steps.variables.outputs.report-path }} + 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 index 521f1dfe94..0e8ffd59ef 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -19,6 +19,13 @@ inputs: 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 @@ -76,7 +83,7 @@ runs: shell: bash run: | echo "git=`command -v git`" >> "$GITHUB_OUTPUT" - echo "sudo=`command -v sudo`" >> "$GITHUB_OUTPUT" + echo "sudo=`sudo true && command -v sudo`" >> "$GITHUB_OUTPUT" echo "autoreconf=`command -v autoreconf`" >> "$GITHUB_OUTPUT" - if: steps.which.outputs.git @@ -88,15 +95,15 @@ runs: git config --global init.defaultBranch garbage - if: inputs.checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: path: ${{ inputs.srcdir }} fetch-depth: ${{ inputs.fetch-depth }} - - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1 + - uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ${{ inputs.srcdir }}/.downloaded-cache - key: downloaded-cache + key: ${{ runner.os }}-${{ runner.arch }}-downloaded-cache - if: steps.which.outputs.autoreconf shell: bash @@ -110,7 +117,7 @@ runs: - if: runner.os == 'Linux' shell: bash - run: echo "GNUMAKEFLAGS=-sj$((1 + $(nproc --all)))" >> "$GITHUB_ENV" + run: echo "GNUMAKEFLAGS=-sj$((1 + $(nproc)))" >> "$GITHUB_ENV" # macOS' GNU make is so old that they doesn't understand `GNUMAKEFLAGS`. - if: runner.os == 'macOS' @@ -121,25 +128,34 @@ runs: shell: bash working-directory: ${{ inputs.srcdir }} run: | - touch config.status - touch .rbconfig.time - sed -f tool/prereq.status template/Makefile.in > Makefile - sed -f tool/prereq.status template/GNUmakefile.in > GNUmakefile + 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 Makefile rbconfig.rb .rbconfig.time + 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 || : - SAVE_IFS="$IFS" IFS=:; set $PATH; dirs=() IFS="$SAVE_IFS" - for d do [ ! -d "$d" ] || dirs+=("$d"); done + 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' @@ -160,13 +176,13 @@ runs: shell: bash id: clean run: | - echo distclean='make -C ${{ inputs.builddir }} distclean' >> $GITHUB_OUTPUT + 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@4683764dd706df847f57b9bed39d08164bcd2690 # v1.4.1 + uses: gacts/run-and-post-run@81b6ce503cde93862cec047c54652e45c5dca991 # v1.4.3 with: working-directory: post: | @@ -174,3 +190,5 @@ runs: ${{ 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 index 24ba48139a..d0072ff828 100644 --- a/.github/actions/setup/macos/action.yml +++ b/.github/actions/setup/macos/action.yml @@ -13,16 +13,17 @@ runs: - name: brew shell: bash run: | - brew install --quiet gmp libffi openssl@3 zlib autoconf automake libtool + brew install --quiet jemalloc gmp libffi openssl@3 zlib autoconf automake libtool - name: Set ENV shell: bash run: | - for lib in gmp; do - ruby_configure_args="${ruby_configure_args:+$ruby_configure_args }--with-${lib%@*}-dir=$(brew --prefix $lib)" - done - for lib in openssl@3; do - CONFIGURE_ARGS="${CONFIGURE_ARGS:+$CONFIGURE_ARGS }--with-${lib%@*}-dir=$(brew --prefix $lib)" - done - echo ruby_configure_args="${ruby_configure_args}" >> $GITHUB_ENV - echo CONFIGURE_ARGS="${CONFIGURE_ARGS}" >> $GITHUB_ENV + 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/slack/action.yml b/.github/actions/slack/action.yml index f0481f5bc2..4a398da1d1 100644 --- a/.github/actions/slack/action.yml +++ b/.github/actions/slack/action.yml @@ -9,7 +9,7 @@ inputs: required: true description: >- The URL to post the payload. This is an input because it tends - to be stored in a secrets valut and a composite action cannot + to be stored in a secrets vault and a composite action cannot look into one. label: @@ -18,6 +18,17 @@ inputs: 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: @@ -33,7 +44,8 @@ runs: "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 == 'push' && startsWith(github.repository, 'ruby/')}} + 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 index 8726df577d..38496d5ceb 100644 --- a/.github/auto_request_review.yml +++ b/.github/auto_request_review.yml @@ -1,13 +1,20 @@ files: - 'yjit*': [team:yjit] - 'yjit/**/*': [team:yjit] + 'yjit*': [team:jit] + 'yjit/**/*': [team:jit] 'yjit/src/cruby_bindings.inc.rs': [] - 'doc/yjit/*': [team:yjit] - 'bootstraptest/test_yjit*': [team:yjit] - 'test/ruby/test_yjit*': [team:yjit] + '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 - # yjit files are modified as well. To be enabled after fixing the behavior. + # files are modified as well. To be enabled after fixing the behavior. #last_files_match_only: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 426893be2a..2c2982d1d4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -16,3 +16,7 @@ updates: 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 index 8cc482c428..899d601aef 100644 --- a/.github/workflows/annocheck.yml +++ b/.github/workflows/annocheck.yml @@ -39,9 +39,7 @@ jobs: if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} @@ -63,7 +61,7 @@ jobs: - run: id working-directory: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: sparse-checkout-cone-mode: false sparse-checkout: /.github @@ -74,9 +72,9 @@ jobs: builddir: build makeup: true - - uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 with: - ruby-version: '3.0' + ruby-version: '3.1' bundler: none # Minimal flags to pass the check. diff --git a/.github/workflows/auto_request_review.yml b/.github/workflows/auto_request_review.yml index ca27244b46..207315a084 100644 --- a/.github/workflows/auto_request_review.yml +++ b/.github/workflows/auto_request_review.yml @@ -2,6 +2,7 @@ name: Auto Request Review on: pull_request_target: types: [opened, ready_for_review, reopened] + branches: [master] permissions: contents: read @@ -16,4 +17,4 @@ jobs: uses: necojackarc/auto-request-review@e89da1a8cd7c8c16d9de9c6e763290b6b0e3d424 # v0.13.0 with: # scope: public_repo - token: ${{ secrets.MATZBOT_GITHUB_TOKEN }} + token: ${{ secrets.MATZBOT_AUTO_REQUEST_REVIEW_TOKEN }} diff --git a/.github/workflows/auto_review_pr.yml b/.github/workflows/auto_review_pr.yml new file mode 100644 index 0000000000..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 3dbf135736..d3e734f885 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -30,14 +30,12 @@ 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.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} @@ -45,18 +43,17 @@ jobs: strategy: matrix: ruby: - - ruby-3.0 - ruby-3.1 - ruby-3.2 - ruby-3.3 steps: - - uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 with: ruby-version: ${{ matrix.ruby }} bundler: none - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: ./.github/actions/setup/ubuntu diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml index da2c7028c2..59f64e8312 100644 --- a/.github/workflows/bundled_gems.yml +++ b/.github/workflows/bundled_gems.yml @@ -1,5 +1,8 @@ name: bundled_gems +env: + UPDATE_ENABLED: true + on: push: branches: ['master'] @@ -31,13 +34,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: - token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup/directories with: - # Skip overwriting MATZBOT_GITHUB_TOKEN + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) - name: Set ENV @@ -56,6 +59,7 @@ jobs: id: bundled_gems run: | ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems >> $GITHUB_OUTPUT + if: ${{ env.UPDATE_ENABLED == 'true' }} - name: Update spec/bundler/support/builders.rb run: | @@ -63,10 +67,12 @@ jobs: 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 @@ -82,6 +88,67 @@ jobs: echo gems=$gems >> $GITHUB_OUTPUT echo update=${news:-$gems} >> $GITHUB_OUTPUT + - name: Commit + id: commit + run: | + git pull --ff-only origin ${GITHUB_REF#refs/heads/} + message="Update bundled gems list" + if [ -z "${gems}" ]; then + git commit --message="[DOC] ${message} at ${GITHUB_SHA:0:30}" + else + git commit --message="${message} as of ${TODAY}" + fi + env: + TODAY: ${{ steps.bundled_gems.outputs.latest_date || env.TODAY }} + EMAIL: svn-admin@ruby-lang.org + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + gems: ${{ steps.diff.outputs.gems }} + if: ${{ steps.diff.outputs.update }} + + - name: Development revision of bundled gems + run: | + #!ruby + file = "gems/bundled_gems" + + SECONDS_IN_DAY = 86400 + today = Time.new("#{ENV['TODAY']}Z") + if !(december = today.month == 12) + days = 30 + elsif (days = 26 - today.day).positive? + days += 4 + else + puts "::info:: just after released" + exit + end + + since = "#{today.year-1}-12-26" + ref = ENV['GITHUB_REF'] + puts "::group::\e[94mfetching \e[1m#{file}\e[22m since \e[1m#{since}\e[22m from \e[1m#{ref}\e[m" + system(*%W[git fetch --shallow-since=#{since} --no-tags origin #{ref}], exception: true) + puts "::endgroup::" + + puts "\e[94mchecking development version bundled gems older than \e[1m#{days}\e[22m days\e[m" + limit = today.to_i - days * SECONDS_IN_DAY + old = 0 + IO.popen(%W"git blame --line-porcelain -- #{file}") do |blame| + while head = blame.gets("\n\t") and s = blame.gets + next unless (gem = s.split(/\s+|#.*/)).size > 3 + time = head[/^committer-time \K\d+/].to_i + next if (d = limit - time) <= 0 + d /= SECONDS_IN_DAY + line = head[/\A\h+ \d+ \K\d+/].to_i + level = if d < days; 'warning'; else old += 1; 'error'; end + d += days + puts "::#{level} file=#{file},line=#{line},title=Older than #{d} days::#{gem[0]} #{gem[3]}" + end + end + abort "::error title=Too long-standing gems::The release comes soon." if december and old.nonzero? + shell: ruby {0} + env: + file: ${{ steps.logs.outputs.file }} + days: ${{ steps.logs.outputs.days }} + - name: Install libraries uses: ./.github/actions/setup/ubuntu if: ${{ steps.diff.outputs.gems }} @@ -104,30 +171,17 @@ jobs: timeout-minutes: 30 env: RUBY_TESTOPTS: '-q --tty=no' - TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'typeprof' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' if: ${{ steps.diff.outputs.gems }} - - name: Commit + - name: Push run: | - git pull --ff-only origin ${GITHUB_REF#refs/heads/} - message="Update bundled gems list" - if [ -z "${gems}" ]; then - git commit --message="${message} at ${GITHUB_SHA:0:30} [ci skip]" - else - git commit --message="${message} as of ${TODAY}" - fi git push origin ${GITHUB_REF#refs/heads/} - env: - TODAY: ${{ steps.bundled_gems.outputs.latest_date || env.TODAY }} - EMAIL: svn-admin@ruby-lang.org - GIT_AUTHOR_NAME: git - GIT_COMMITTER_NAME: git - gems: ${{ steps.diff.outputs.gems }} if: >- ${{ github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull') && - steps.diff.outputs.update + steps.commit.outcome == 'success' }} - uses: ./.github/actions/slack diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index 5536396b86..c5dec65e48 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -9,13 +9,6 @@ on: - '**/.document' - '.*.yml' pull_request: - paths-ignore: - - 'doc/**' - - '**/man/*' - - '**.md' - - '**.rdoc' - - '**/.document' - - '.*.yml' merge_group: concurrency: @@ -27,25 +20,17 @@ permissions: jobs: update-deps: + name: Dependency checks + strategy: matrix: - os: [ubuntu-20.04] + os: [ubuntu-latest] fail-fast: true runs-on: ${{ matrix.os }} - if: >- - ${{!(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.head_commit.message, 'Document') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') - )}} - steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: ./.github/actions/setup/ubuntu if: ${{ contains(matrix.os, 'ubuntu') }} @@ -55,19 +40,15 @@ jobs: - uses: ./.github/actions/setup/directories - - uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 + - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0 with: - ruby-version: '3.0' + 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: ./goruby -veh - - - run: ruby tool/update-deps --fix + - run: make fix-depends - run: git diff --no-ext-diff --ignore-submodules --exit-code diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml index 5c6a95a05d..2a2bd1df53 100644 --- a/.github/workflows/check_misc.yml +++ b/.github/workflows/check_misc.yml @@ -18,24 +18,25 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: - token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup/directories with: makeup: true - # Skip overwriting MATZBOT_GITHUB_TOKEN + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) - - name: Check if C-sources are US-ASCII + - name: Check for code styles run: | - grep -r -n --include='*.[chyS]' --include='*.asm' $'[^\t-~]' -- . && exit 1 || : - - - name: Check for trailing spaces - run: | - git grep -I -n $'[\t ]$' -- '*.rb' '*.[chy]' '*.rs' '*.yml' && exit 1 || : - git grep -n $'^[\t ][\t ]*$' -- '*.md' && exit 1 || : + set -x + ruby tool/auto-style.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" + env: + GITHUB_OLD_SHA: ${{ github.event.pull_request.base.sha }} + GITHUB_NEW_SHA: ${{ github.event.pull_request.merge_commit_sha }} + # Skip 'push' events because post_push.yml fixes them on push + if: ${{ github.repository == 'ruby/ruby' && startsWith(github.event_name, 'pull') }} - name: Check for bash specific substitution in configure.ac run: | @@ -52,83 +53,69 @@ jobs: exit $fail working-directory: include - - id: gems - run: true - if: ${{ github.ref == 'refs/heads/master' }} - - - name: Download previous gems list + - id: now run: | - data=default_gems.json - mkdir -p .downloaded-cache - ln -s .downloaded-cache/$data . - curl -O -R -z ./$data https://stdgems.org/$data - if: ${{ steps.gems.outcome == 'success' }} + date +"mon=%-m"%n"day=%-d" >> $GITHUB_OUTPUT + env: + TZ: Tokyo/Asia - - name: Make default gems list + - id: deprecation run: | - #!ruby - require 'rubygems' - $:.unshift "lib" - rgver = File.foreach("lib/rubygems.rb") do |line| - break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line - end - gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f| - spec = Gem::Specification.load(f) - "#{spec.name} #{spec.version}" - end.sort - File.open("gems/default_gems", "w") do |f| - f.puts "RubyGems #{rgver}" - f.puts gems - end - shell: ruby --disable=gems {0} - if: ${{ steps.gems.outcome == 'success' }} - - - name: Maintain updated gems list in NEWS + eval $(sed -n 's/^#define RUBY_API_VERSION_\(MAJOR\|MINOR\) /\1=/p' include/ruby/version.h) + if git --no-pager grep --color -o 'rb_warn_deprecated_to_remove_at('$MAJOR'\.'$MINOR',.*' -- '*.c' >&2; then + false + else + true + fi + continue-on-error: ${{ steps.now.outputs.mon < 12 }} + + - name: Check if to generate documents + id: rdoc run: | - ruby tool/update-NEWS-gemlist.rb default - if: ${{ steps.gems.outcome == 'success' }} + set -- $(sed 's/#.*//;/^rdoc /!d' gems/bundled_gems) + { echo version=$2; echo ref=$4; } >> $GITHUB_OUTPUT + echo RDOC='ruby -W0 --disable-gems tool/rdoc-srcdir -q' >> $GITHUB_ENV - - 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: 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: Commit + - name: Generate rdoc 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 - }} + 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: | - ruby -W0 --disable-gems -I./lib tool/rdoc-srcdir -q --op html . + $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.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') }} - name: Upload docs - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6.0.0 with: path: html name: ${{ steps.docs.outputs.htmlout }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 32c4951859..a92c93b476 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -41,9 +41,7 @@ jobs: if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} @@ -60,7 +58,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Install libraries if: ${{ contains(matrix.os, 'macos') }} @@ -77,15 +75,17 @@ jobs: run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb - name: Initialize CodeQL - uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 with: languages: ${{ matrix.language }} + trap-caching: false + debug: true - name: Autobuild - uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + uses: github/codeql-action/autobuild@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 with: category: '/language:${{ matrix.language }}' upload: False @@ -115,7 +115,7 @@ jobs: continue-on-error: true - name: Upload SARIF - uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + 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 785ed5a8d8..8c0ca54e0b 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -29,23 +29,32 @@ permissions: # Each job is split so that they roughly take 30min to run through. jobs: - compile1: - name: 'omnibus compilations, #1' + compile-if: + name: 'omnibus compilations, trigger' runs-on: ubuntu-latest if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} + steps: + - run: true + working-directory: + + compile1: + name: 'omnibus compilations, #1' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - 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. + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } - name: 'clang 18 LTO' uses: './.github/actions/compilers' with: @@ -53,307 +62,244 @@ jobs: with_gcc: 'clang-18 -flto=auto' optflags: '-O2' enable_shared: false - - name: 'GCC 13 LTO' - uses: './.github/actions/compilers' - with: - tag: gcc-13 - with_gcc: 'gcc-13 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch' - 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 - if: >- - ${{!(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.head_commit.message, 'Document') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') - )}} + 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@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - 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: './.github/actions/compilers', name: 'GCC 13', with: { tag: 'gcc-13' } } - - { uses: './.github/actions/compilers', name: 'GCC 12', with: { tag: 'gcc-12' } } - - { uses: './.github/actions/compilers', name: 'GCC 11', with: { tag: 'gcc-11' } } - - { uses: './.github/actions/compilers', name: 'GCC 10', with: { tag: 'gcc-10' } } - - { uses: './.github/actions/compilers', name: 'GCC 9', with: { tag: 'gcc-9' } } - - { uses: './.github/actions/compilers', name: 'GCC 8', with: { tag: 'gcc-8' } } - - { uses: './.github/actions/compilers', name: 'GCC 7', with: { tag: 'gcc-7' } } + - { 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 - if: >- - ${{!(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.head_commit.message, 'Document') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') - )}} + 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@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - 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: './.github/actions/compilers', name: 'clang 20', with: { tag: 'clang-20' } } - - { uses: './.github/actions/compilers', name: 'clang 19', with: { tag: 'clang-19' } } - - { uses: './.github/actions/compilers', name: 'clang 18', with: { tag: 'clang-18' } } - - { uses: './.github/actions/compilers', name: 'clang 17', with: { tag: 'clang-17' } } - - { uses: './.github/actions/compilers', name: 'clang 16', with: { tag: 'clang-16' } } - - { uses: './.github/actions/compilers', name: 'clang 15', with: { tag: 'clang-15' } } - - { uses: './.github/actions/compilers', name: 'clang 14', with: { tag: 'clang-14' } } - - { uses: './.github/actions/compilers', name: 'clang 13', with: { tag: 'clang-13' } } - - { uses: './.github/actions/compilers', name: 'clang 12', with: { tag: 'clang-12' } } + - { 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 - if: >- - ${{!(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.head_commit.message, 'Document') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') - )}} + 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@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - 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: './.github/actions/compilers', name: 'clang 11', with: { tag: 'clang-11' } } - - { uses: './.github/actions/compilers', name: 'clang 10', with: { tag: 'clang-10' } } - # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o. - - { uses: './.github/actions/compilers', name: 'clang 9', with: { tag: 'clang-9', append_configure: '--disable-yjit' } } - - { uses: './.github/actions/compilers', name: 'clang 8', with: { tag: 'clang-8', append_configure: '--disable-yjit' } } - - { uses: './.github/actions/compilers', name: 'clang 7', with: { tag: 'clang-7', append_configure: '--disable-yjit' } } - - { uses: './.github/actions/compilers', name: 'clang 6', with: { tag: 'clang-6.0', append_configure: '--disable-yjit' } } - - { uses: './.github/actions/compilers', name: 'ext/Setup', with: { static_exts: 'etc json/* */escape' } } + - { 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 - if: >- - ${{!(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.head_commit.message, 'Document') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.title, 'Document') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') - )}} + 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@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - 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: './.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' } } - - { uses: './.github/actions/compilers', name: 'C11', with: { CFLAGS: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } - - { uses: './.github/actions/compilers', name: 'C17', with: { CFLAGS: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } - - { uses: './.github/actions/compilers', name: 'C23', with: { CFLAGS: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } |