From 634eae70c87c2dfac9e09dbb0dcfb987e0c2fb71 Mon Sep 17 00:00:00 2001 From: Myron Marston Date: Fri, 27 Dec 2024 18:12:44 -0800 Subject: [PATCH] Validate our gemspecs using an RSpec test. This replaces the validation we were doing in `gemspec_helper.rb`. The `gemspec_helper.rb` file doesn't appear to be compatible with dependabot, and we're going to stop using it in a later PR. --- elasticgraph/spec/spec_helper.rb | 11 +++ .../spec/unit/elastic_graph/gem_spec.rb | 70 +++++++++++++++++++ gemspec_helper.rb | 61 ---------------- 3 files changed, 81 insertions(+), 61 deletions(-) create mode 100644 elasticgraph/spec/spec_helper.rb create mode 100644 elasticgraph/spec/unit/elastic_graph/gem_spec.rb diff --git a/elasticgraph/spec/spec_helper.rb b/elasticgraph/spec/spec_helper.rb new file mode 100644 index 00000000..930407a1 --- /dev/null +++ b/elasticgraph/spec/spec_helper.rb @@ -0,0 +1,11 @@ +# Copyright 2024 Block, Inc. +# +# Use of this source code is governed by an MIT-style +# license that can be found in the LICENSE file or at +# https://opensource.org/licenses/MIT. +# +# frozen_string_literal: true + +# This file is contains RSpec configuration and common support code for `elasticgraph`. +# Note that it gets loaded by `spec_support/spec_helper.rb` which contains common spec support +# code for all ElasticGraph test suites. diff --git a/elasticgraph/spec/unit/elastic_graph/gem_spec.rb b/elasticgraph/spec/unit/elastic_graph/gem_spec.rb new file mode 100644 index 00000000..e54fadc4 --- /dev/null +++ b/elasticgraph/spec/unit/elastic_graph/gem_spec.rb @@ -0,0 +1,70 @@ +# Copyright 2024 Block, Inc. +# +# Use of this source code is governed by an MIT-style +# license that can be found in the LICENSE file or at +# https://opensource.org/licenses/MIT. +# +# frozen_string_literal: true + +require_relative "../../../../script/list_eg_gems" + +module ElasticGraph + RSpec.describe "ElasticGraph gems" do + gemspecs_by_gem_name = ::Hash.new do |hash, gem_name| + hash[gem_name] = begin + gemspec_file = ::File.join(CommonSpecHelpers::REPO_ROOT, gem_name, "#{gem_name}.gemspec") + eval(::File.read(gemspec_file), ::TOPLEVEL_BINDING.dup, gemspec_file) # standard:disable Security/Eval + end + end + + shared_examples_for "an ElasticGraph gem" do |gem_name| + around do |ex| + ::Dir.chdir(::File.join(CommonSpecHelpers::REPO_ROOT, gem_name), &ex) + end + + let(:gemspec) { gemspecs_by_gem_name[gem_name] } + + it "has the correct name" do + expect(gemspec.name).to eq gem_name + end + + it "has no symlinked files included in the gem since they do not work correctly when the gem is packaged packaged" do + symlink_files = gemspec.files.select { |f| ::File.exist?(f) && ::File.ftype(f) == "link" } + expect(symlink_files).to be_empty + end + + %w[.yardopts Gemfile .rspec].each do |file| + it "has a symlinked `#{file}` file" do + expect(::File.exist?(file)).to be true + expect(::File.ftype(file)).to eq "link" + end + end + + it "has a non-symlinked `LICENSE.txt` file" do + expect(::File.exist?("LICENSE.txt")).to be true + expect(::File.ftype("LICENSE.txt")).to eq "file" + expect(::File.read("LICENSE.txt")).to include("MIT License", "Copyright (c) 2024 Block, Inc.") + end + end + + ::ElasticGraphGems.list.each do |gem_name| + describe gem_name do + include_examples "an ElasticGraph gem", gem_name + end + end + + # We don't expect any variation in these gemspec attributes. + %i[authors email homepage license required_ruby_version version].each do |gemspec_attribute| + it "has the same value for `#{gemspec_attribute}` in all ElasticGraph gemspecs" do + all_gemspec_values = ::ElasticGraphGems.list.to_h do |gem_name| + [gem_name, gemspecs_by_gem_name[gem_name].public_send(gemspec_attribute)] + end + + most_common_value = all_gemspec_values.values.tally.max_by { |_, count| count }.first + nonstandard_gemspec_values = all_gemspec_values.select { |_, value| value != most_common_value } + + expect(nonstandard_gemspec_values).to be_empty + end + end + end +end diff --git a/gemspec_helper.rb b/gemspec_helper.rb index 198c5177..4f52857c 100644 --- a/gemspec_helper.rb +++ b/gemspec_helper.rb @@ -12,7 +12,6 @@ module ElasticGraphGemspecHelper # Helper methor for defining a gemspec for an elasticgraph gem. def self.define_elasticgraph_gem(gemspec_file:, category:) gem_dir = ::File.expand_path(::File.dirname(gemspec_file)) - validate_gem(gem_dir) ::Gem::Specification.new do |spec| spec.name = ::File.basename(gemspec_file, ".gemspec") @@ -48,66 +47,6 @@ def self.define_elasticgraph_gem(gemspec_file:, category:) spec.required_ruby_version = "~> 3.2" yield spec, ElasticGraph::VERSION - - if (symlink_files = spec.files.select { |f| ::File.exist?(f) && ::File.ftype(f) == "link" }).any? - raise "#{symlink_files.size} file(s) of the `#{spec.name}` gem are symlinks, but " \ - "symlinks do not work correctly when the gem is packaged. Symlink files: #{symlink_files.inspect}" - end - end - end - - def self.validate_gem(gem_dir) - gem_warnings = validate_symlinked_file(::File.join(gem_dir, ".yardopts")) - - gem_issues = [] - gem_issues.concat(validate_symlinked_file(::File.join(gem_dir, "Gemfile"))) - gem_issues.concat(validate_symlinked_file(::File.join(gem_dir, ".rspec"))) - gem_issues.concat(validate_license(gem_dir)) - - unless gem_warnings.empty? - warn "WARNING: Gem #{::File.basename(gem_dir)} has the following issues:\n\n" + gem_warnings.join("\n") end - - return if gem_issues.empty? - - abort "Gem #{::File.basename(gem_dir)} has the following issues:\n\n" + gem_issues.join("\n") - end - - def self.validate_symlinked_file(file) - gem_issues = [] - - if ::File.exist?(file) - if ::File.ftype(file) != "link" - gem_issues << "`#{file}` must be a symlink." - end - else - gem_issues << "`#{file}` is missing." - end - - gem_issues - end - - def self.validate_license(gem_dir) - gem_issues = [] - - file = ::File.join(gem_dir, "LICENSE.txt") - if ::File.exist?(file) - if ::File.ftype(file) == "link" - gem_issues << "`#{file}` must not be a symlink." - end - - contents = ::File.read(file) - unless contents.include?("MIT License") - gem_issues << "`#{file}` must contain 'MIT License'." - end - - unless contents.include?("Copyright (c) 2024 Block, Inc.") - gem_issues << "`#{file}` must contain Block copyright notice." - end - else - gem_issues << "`#{file}` is missing." - end - - gem_issues end end