diff --git a/.github/actions/typed-core/action.yml b/.github/actions/typed-core/action.yml index 9c1873b35..44db495ee 100644 --- a/.github/actions/typed-core/action.yml +++ b/.github/actions/typed-core/action.yml @@ -28,13 +28,3 @@ runs: ' "${export_root}/core-ruby-artifact.json" # kettle-test discovers the owning gem from the bundle's directory. cp "${GITHUB_WORKSPACE}/.github/typed_core.gemfile" "${STRUCTUREDMERGE_CI_GEM_DIR}/ci_core.gemfile" - - name: Clean stale version_gem versions - shell: bash - run: | - # RubyGems emits a warning when multiple versions of a gem with - # conflicting requirements are installed. Registry kettle-dev family - # gems (floor 1.1.15) conflict with local structuredmerge gems - # (floor 1.1.16). Keep only the version required by the local gems. - if gem list version_gem --exact | grep -q 1.1.15; then - gem uninstall version_gem -v 1.1.15 - fi diff --git a/.github/typed_core.gemfile b/.github/typed_core.gemfile index 1bcbb6da5..57b44d5a1 100644 --- a/.github/typed_core.gemfile +++ b/.github/typed_core.gemfile @@ -33,11 +33,3 @@ if ENV.fetch('STRUCTUREDMERGE_DEV', '').strip != '' end end end - -# Prevent the registry version_gem 1.1.15 from being resolved alongside 1.1.16 -# when registry development gems (kettle-dev, kettle-family, kettle-test) with -# the older floor are present. The local structuredmerge gems require >= 1.1.16. -if dependencies.any? { |dependency| dependency.name == "version_gem" } - instance_variable_get(:@dependencies).reject! { |dependency| dependency.name == "version_gem" } - gem "version_gem", "~> 1.1", ">= 1.1.16" -end diff --git a/.github/workflows/current.yml b/.github/workflows/current.yml index a1ab24b2f..f81e3d57b 100644 --- a/.github/workflows/current.yml +++ b/.github/workflows/current.yml @@ -535,6 +535,10 @@ jobs: needs: detect if: ${{ needs.detect.outputs.release_mode == '' }} runs-on: ubuntu-latest + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gems/ast-merge-git/Appraisal.root.gemfile + K_JEM_TEMPLATING: true + STRUCTUREDMERGE_DEV: ${{ github.workspace }}/gems steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -555,43 +559,17 @@ jobs: test "$(git -C ../benchmark-fixtures rev-parse "refs/tags/${tag}^{commit}")" = "${revision}" - name: Setup Ruby uses: appraisal-rb/setup-ruby-flash@6f8ad36ba7488db591541483afb5464d01e8861b # v2.14 + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gems/ast-merge-git/Appraisal.root.gemfile + K_JEM_TEMPLATING: true + STRUCTUREDMERGE_DEV: ${{ github.workspace }}/gems with: ruby-version: ruby bundler-cache: false + main-bundle-install: false working-directory: gems/ast-merge-git - pre-bundle-gems: | - nomono --source https://gem.coop --source https://rubygems.org - - name: Install dependencies - working-directory: gems/ast-merge-git - env: - K_JEM_TEMPLATING: true - STRUCTUREDMERGE_DEV: ${{ github.workspace }}/gems - # BUNDLE_GEMFILE must be set for THIS step too: GITHUB_ENV only - # applies to later steps, so without this the install resolves the - # default Gemfile while the benchmark step resolves - # ci_benchmark.gemfile — whose git-sourced gems are then not - # checked out ("not yet checked out" Bundler::GitError). - BUNDLE_GEMFILE: ${{ runner.temp }}/ci_benchmark.gemfile - run: | - bundle config set frozen false - # Pin version_gem to avoid 1.1.15/1.1.16 dual-resolution from - # registry kettle-dev family gems (older floor) vs local gems - cat > "${RUNNER_TEMP}/ci_benchmark.gemfile" < 1.1', '>= 1.1.16' - EOF - echo "BUNDLE_GEMFILE=${RUNNER_TEMP}/ci_benchmark.gemfile" >> "${GITHUB_ENV}" - for attempt in 1 2 3; do - if bundle install --jobs 4 --retry 8; then - exit 0 - fi - - if [[ "${attempt}" -lt 3 ]]; then - sleep "$((attempt * 5))" - fi - done - - exit 1 + appraisal-name: benchmark-dev + appraisal-root-gemfile: Appraisal.root.gemfile - name: Run affected-capability benchmark working-directory: gems/ast-merge-git env: @@ -619,7 +597,7 @@ jobs: mkdir -p "$(dirname "${report}")" set +e - timeout 5m bundle exec ast-merge-git benchmark report \ + timeout 5m bundle exec appraisal benchmark-dev bundle exec ast-merge-git benchmark report \ --corpus "${corpus}" \ --profile dev \ --tmp-root "${PWD}/tmp/ci-benchmark/run" \ @@ -701,35 +679,26 @@ jobs: needs: detect if: ${{ needs.detect.outputs.release_mode == '' }} runs-on: ubuntu-latest + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gems/tree_haver/Appraisal.root.gemfile + K_JEM_TEMPLATING: true + STRUCTUREDMERGE_DEV: ${{ github.workspace }}/gems steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Setup Ruby uses: appraisal-rb/setup-ruby-flash@6f8ad36ba7488db591541483afb5464d01e8861b # v2.14 + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gems/tree_haver/Appraisal.root.gemfile + K_JEM_TEMPLATING: true + STRUCTUREDMERGE_DEV: ${{ github.workspace }}/gems with: ruby-version: ruby bundler-cache: false + main-bundle-install: false working-directory: gems/tree_haver - pre-bundle-gems: | - nomono --source https://gem.coop --source https://rubygems.org - - name: Install dependencies - working-directory: gems/tree_haver - env: - K_JEM_TEMPLATING: true - STRUCTUREDMERGE_DEV: ${{ github.workspace }}/gems - run: | - bundle config set frozen false - for attempt in 1 2 3; do - if bundle install --jobs 4 --retry 8; then - exit 0 - fi - - if [[ "${attempt}" -lt 3 ]]; then - sleep "$((attempt * 5))" - fi - done - - exit 1 + appraisal-name: tslp-cold-start + appraisal-root-gemfile: Appraisal.root.gemfile - name: Run cold-start TSLP checks working-directory: gems/tree_haver env: @@ -740,7 +709,7 @@ jobs: set -euo pipefail export TREE_SITTER_LANGUAGE_PACK_CACHE_DIR TREE_SITTER_LANGUAGE_PACK_CACHE_DIR="$(mktemp -d "${RUNNER_TEMP}/tslp-cold-start.XXXXXX")" - bundle exec rspec spec/grammar_finder_spec.rb spec/backends/tslp_spec.rb --format progress + bundle exec appraisal tslp-cold-start bundle exec rspec spec/grammar_finder_spec.rb spec/backends/tslp_spec.rb --format progress check: name: Check diff --git a/gems/ast-merge-git/Appraisal.root.gemfile b/gems/ast-merge-git/Appraisal.root.gemfile new file mode 100644 index 000000000..87a8fb37e --- /dev/null +++ b/gems/ast-merge-git/Appraisal.root.gemfile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +source "https://gem.coop" + +# Shared baseline for the Appraisal2 CI lanes in this gem. +gemspec + +gem "nomono", "~> 1.1", ">= 1.1.14" diff --git a/gems/ast-merge-git/Appraisals b/gems/ast-merge-git/Appraisals new file mode 100644 index 000000000..35053a447 --- /dev/null +++ b/gems/ast-merge-git/Appraisals @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +appraise "benchmark-dev" do + eval_gemfile "modular/templating.gemfile" + eval_gemfile "modular/x_std_libs.gemfile" +end diff --git a/gems/kettle-jem/lib/kettle/jem.rb b/gems/kettle-jem/lib/kettle/jem.rb index 18f314984..bb7124d23 100644 --- a/gems/kettle-jem/lib/kettle/jem.rb +++ b/gems/kettle-jem/lib/kettle/jem.rb @@ -14752,7 +14752,7 @@ def template_tokens(facts, funding) "KJ|CI:EXEC_CMD" => facts.dig(:ci, :exec_cmd).to_s, "KJ|CI:OS_MATRIX_ENTRIES" => github_actions_current_os_matrix_entries(facts), "KJ|CI:OS_TEST_STEPS" => github_actions_current_os_test_steps(facts), - "KJ|README:PLATFORM_SUPPORT_TABLE" => readme_platform_support_table(facts), + "KJ|README:CI_COVERAGE_SUMMARY" => readme_ci_coverage_summary(facts), "KJ|RAKE:TOP_LEVEL_DOCS_TASK" => rake_top_level_docs_task_token(facts).rstrip, "KJ|GITHUB_ACTIONS:COVERAGE_UPLOAD_STEPS" => github_actions_coverage_steps(disabled_integrations: facts.dig(:integrations, :disabled)) }.merge( @@ -14827,66 +14827,13 @@ def readme_title_token(package, rubygems) "#{package_name} / #{namespace}" end - # The README platform tier table, generated from the same facts that drive - # the workflows, so it cannot drift from CI again (spec slice 1038). Rows - # mirror the generated workflow set: versioned MRI workflows are Linux-only, - # the current.yml OS matrix covers the declared platforms for MRI current, - # and every engine lane outside current.yml is Linux-only. Engine capability - # notes come from Kettle::Rb::PlatformSupport and carry their citation. - def readme_platform_support_table(facts) - engines = facts.dig(:rubygems, :engines) - engines = DEFAULT_ENGINES if engines.nil? || engines.empty? + # Keep the README's CI statement concise and limited to the generated facts. + # The compatibility badge table already carries engine/version detail; + # this adds only the declared OS platforms for the current-runtime matrix. + def readme_ci_coverage_summary(facts) platforms = facts.dig(:ci, :platforms) platforms = DEFAULT_PLATFORMS if platforms.nil? || platforms.empty? - ruby_versions = facts.dig(:ci, :ruby_versions).to_a.map(&:to_s).reject(&:empty?) - - parallel = "Parallel support" - unsupported = "Unsupported" - rows = [] - - unless ruby_versions.empty? - rows << [ - "MRI #{ruby_versions.first}-#{ruby_versions.last}", - parallel, unsupported, unsupported, - "Versioned Ruby workflows run on Linux." - ] - end - rows << [ - "MRI current", - parallel, - platforms.include?("macos") ? parallel : unsupported, - platforms.include?("windows") ? parallel : unsupported, - "Current Ruby workflow covers the declared OS platforms." - ] - rows << [ - "MRI head", - parallel, unsupported, unsupported, - "CI is allowed to fail while Ruby is in development." - ] - - (engines - ["ruby"]).each do |engine| - label = (engine == "jruby") ? "JRuby" : "TruffleRuby" - windows_entry = Kettle::Rb::PlatformSupport.engine_os_entry(engine, "windows") - note = if windows_entry && windows_entry.support == "unsupported" - "#{windows_entry.note} ([source](#{windows_entry.citation}))" - else - "Engine workflows run on Linux; macOS and Windows are not exercised by CI." - end - rows << ["#{label} (all CI lanes)", parallel, unsupported, unsupported, note] - end - - [ - "Support tiers describe what this project's CI actually exercises, not what may", - "work in an untested environment:", - "", - "- **Parallel support**: CI runs the test suite with multiple workers available.", - "- **Unsupported**: the engine/platform combination is not covered by CI and is", - " not a project compatibility claim.", - "", - "| Ruby engine/version | Linux | macOS | Windows | Notes |", - "|---------------------|-------|-------|---------|-------|", - *rows.map { |row| "| #{row.join(" | ")} |" } - ].join("\n") + "The current MRI runtime matrix runs on #{platforms.join(", ")}." end def readme_dev_test_stack_table(package_name) diff --git a/gems/kettle-jem/lib/kettle/jem/templates/README.md.example b/gems/kettle-jem/lib/kettle/jem/templates/README.md.example index 8a6557930..9af93fdf8 100644 --- a/gems/kettle-jem/lib/kettle/jem/templates/README.md.example +++ b/gems/kettle-jem/lib/kettle/jem/templates/README.md.example @@ -64,9 +64,9 @@ The _amazing_ test matrix is powered by the kettle-dev stack. {KJ|README:FAMILY_INTRO_BACKEND_MATRIX} -### Runtime and Platform Support +### CI Coverage -{KJ|README:PLATFORM_SUPPORT_TABLE} +{KJ|README:CI_COVERAGE_SUMMARY} ### Federated DVCS diff --git a/gems/kettle-jem/spec/kettle/jem_platforms_config_spec.rb b/gems/kettle-jem/spec/kettle/jem_platforms_config_spec.rb index 102b085f0..4c5b29a0e 100644 --- a/gems/kettle-jem/spec/kettle/jem_platforms_config_spec.rb +++ b/gems/kettle-jem/spec/kettle/jem_platforms_config_spec.rb @@ -195,45 +195,22 @@ def ci_facts(platforms, exec_cmd: "bundle exec kettle-test") end end - describe "readme_platform_support_table" do - def table_facts(engines:, platforms:, ruby_versions: %w[2.4 3.4]) - {rubygems: {engines: engines}, ci: {platforms: platforms, ruby_versions: ruby_versions}} + describe "readme_ci_coverage_summary" do + def summary_facts(platforms:) + {ci: {platforms: platforms}} end - it "marks macOS and Windows by the declared platforms for MRI current only" do - table = described_class.send(:readme_platform_support_table, table_facts(engines: %w[ruby], platforms: %w[linux macos windows])) + it "summarizes the current-runtime OS matrix without engine/version claims" do + summary = described_class.send(:readme_ci_coverage_summary, summary_facts(platforms: %w[linux macos])) - expect(table).to include("| MRI current | Parallel support | Parallel support | Parallel support |") - expect(table).to include("| MRI 2.4-3.4 | Parallel support | Unsupported | Unsupported |") - expect(table).to include("| MRI head | Parallel support | Unsupported | Unsupported |") + expect(summary).to eq("The current MRI runtime matrix runs on linux, macos.") + expect(summary).not_to include("JRuby", "TruffleRuby", "all CI lanes", "Parallel support", "Unsupported", "MRI 2.4") end - it "marks Windows unsupported for MRI current when it is not declared" do - table = described_class.send(:readme_platform_support_table, table_facts(engines: %w[ruby], platforms: %w[linux macos])) + it "falls back to configured defaults when facts are absent" do + summary = described_class.send(:readme_ci_coverage_summary, {}) - expect(table).to include("| MRI current | Parallel support | Parallel support | Unsupported |") - end - - it "evidences the TruffleRuby Windows exclusion with a cited note" do - table = described_class.send(:readme_platform_support_table, table_facts(engines: %w[ruby truffleruby], platforms: %w[linux macos windows])) - - expect(table).to include("| TruffleRuby (all CI lanes) | Parallel support | Unsupported | Unsupported |") - expect(table).to include("Never shipped a Windows build") - expect(table).to include("([source](https://") - end - - it "keeps engine lanes Linux-only even when Windows is declared" do - table = described_class.send(:readme_platform_support_table, table_facts(engines: %w[ruby jruby], platforms: %w[linux macos windows])) - - expect(table).to include("| JRuby (all CI lanes) | Parallel support | Unsupported | Unsupported |") - end - - it "falls back to defaults when facts are absent" do - table = described_class.send(:readme_platform_support_table, {}) - - expect(table).to include("| MRI current | Parallel support | Parallel support | Unsupported |") - expect(table).to include("| TruffleRuby (all CI lanes) |") - expect(table).to include("| JRuby (all CI lanes) |") + expect(summary).to eq("The current MRI runtime matrix runs on linux, macos.") end end diff --git a/gems/tree_haver/Appraisal.root.gemfile b/gems/tree_haver/Appraisal.root.gemfile new file mode 100644 index 000000000..87a8fb37e --- /dev/null +++ b/gems/tree_haver/Appraisal.root.gemfile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +source "https://gem.coop" + +# Shared baseline for the Appraisal2 CI lanes in this gem. +gemspec + +gem "nomono", "~> 1.1", ">= 1.1.14" diff --git a/gems/tree_haver/Appraisals b/gems/tree_haver/Appraisals new file mode 100644 index 000000000..56d57e6e3 --- /dev/null +++ b/gems/tree_haver/Appraisals @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +appraise "tslp-cold-start" do + eval_gemfile "modular/templating.gemfile" + eval_gemfile "modular/x_std_libs.gemfile" +end