From e9cb0b95e7ade0bccaeb0f7dfa2b6f520bc9a989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mar=C3=ADa=20a=2E=20matienzo?= Date: Thu, 24 Jul 2025 09:03:31 -0700 Subject: [PATCH 1/6] update ruby, rubocop, and add cop changes --- .rubocop.yml | 138 ++++++++++++++++++++++++++++++++++ berkeley_library-util.gemspec | 14 ++-- rakelib/.rubocop.yml | 2 +- spec/.rubocop.yml | 9 ++- 4 files changed, 151 insertions(+), 12 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index d5e423c..bac92dd 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -491,3 +491,141 @@ Style/RedundantStringEscape: # (new in 1.37) Style/RedundantEach: # (new in 1.38) Enabled: true +Gemspec/AddRuntimeDependency: # new in 1.65 + Enabled: true +Gemspec/AttributeAssignment: # new in 1.77 + Enabled: true +Gemspec/DevelopmentDependencies: # new in 1.44 + Enabled: false +Lint/ArrayLiteralInRegexp: # new in 1.71 + Enabled: true +Lint/ConstantReassignment: # new in 1.70 + Enabled: true +Lint/CopDirectiveSyntax: # new in 1.72 + Enabled: true +Lint/DuplicateMatchPattern: # new in 1.50 + Enabled: true +Lint/DuplicateSetElement: # new in 1.67 + Enabled: true +Lint/HashNewWithKeywordArgumentsAsDefault: # new in 1.69 + Enabled: true +Lint/ItWithoutArgumentsInBlock: # new in 1.59 + Enabled: true +Lint/LiteralAssignmentInCondition: # new in 1.58 + Enabled: true +Lint/MixedCaseRange: # new in 1.53 + Enabled: true +Lint/NumericOperationWithConstantResult: # new in 1.69 + Enabled: true +Lint/RedundantRegexpQuantifiers: # new in 1.53 + Enabled: true +Lint/RedundantTypeConversion: # new in 1.72 + Enabled: true +Lint/SharedMutableDefault: # new in 1.70 + Enabled: true +Lint/SuppressedExceptionInNumberConversion: # new in 1.72 + Enabled: true +Lint/UnescapedBracketInRegexp: # new in 1.68 + Enabled: true +Lint/UselessConstantScoping: # new in 1.72 + Enabled: true +Lint/UselessDefaultValueArgument: # new in 1.76 + Enabled: true +Lint/UselessDefined: # new in 1.69 + Enabled: true +Lint/UselessNumericOperation: # new in 1.66 + Enabled: true +Lint/UselessOr: # new in 1.76 + Enabled: true +Lint/UselessRescue: # new in 1.43 + Enabled: true +Metrics/CollectionLiteralLength: # new in 1.47 + Enabled: true +Naming/PredicateMethod: # new in 1.76 + Enabled: true +Style/AmbiguousEndlessMethodDefinition: # new in 1.68 + Enabled: true +Style/ArrayIntersect: # new in 1.40 + Enabled: true +Style/BitwisePredicate: # new in 1.68 + Enabled: true +Style/CollectionQuerying: # new in 1.77 + Enabled: true +Style/CombinableDefined: # new in 1.68 + Enabled: true +Style/ComparableBetween: # new in 1.74 + Enabled: true +Style/ComparableClamp: # new in 1.44 + Enabled: true +Style/ConcatArrayLiterals: # new in 1.41 + Enabled: true +Style/DataInheritance: # new in 1.49 + Enabled: true +Style/DigChain: # new in 1.69 + Enabled: true +Style/DirEmpty: # new in 1.48 + Enabled: true +Style/EmptyStringInsideInterpolation: # new in 1.76 + Enabled: true +Style/ExactRegexpMatch: # new in 1.51 + Enabled: true +Style/FileEmpty: # new in 1.48 + Enabled: true +Style/FileNull: # new in 1.69 + Enabled: true +Style/FileTouch: # new in 1.69 + Enabled: true +Style/HashFetchChain: # new in 1.75 + Enabled: true +Style/HashSlice: # new in 1.71 + Enabled: true +Style/ItAssignment: # new in 1.70 + Enabled: true +Style/ItBlockParameter: # new in 1.75 + Enabled: true +Style/KeywordArgumentsMerging: # new in 1.68 + Enabled: true +Style/MapIntoArray: # new in 1.63 + Enabled: true +Style/MapToSet: # new in 1.42 + Enabled: true +Style/MinMaxComparison: # new in 1.42 + Enabled: true +Style/RedundantArrayConstructor: # new in 1.52 + Enabled: true +Style/RedundantArrayFlatten: # new in 1.76 + Enabled: true +Style/RedundantConstantBase: # new in 1.40 + Enabled: true +Style/RedundantCurrentDirectoryInPath: # new in 1.53 + Enabled: true +Style/RedundantDoubleSplatHashBraces: # new in 1.41 + Enabled: true +Style/RedundantFilterChain: # new in 1.52 + Enabled: true +Style/RedundantFormat: # new in 1.72 + Enabled: true +Style/RedundantHeredocDelimiterQuotes: # new in 1.45 + Enabled: true +Style/RedundantInterpolationUnfreeze: # new in 1.66 + Enabled: true +Style/RedundantLineContinuation: # new in 1.49 + Enabled: true +Style/RedundantRegexpArgument: # new in 1.53 + Enabled: true +Style/RedundantRegexpConstructor: # new in 1.52 + Enabled: true +Style/ReturnNilInPredicateMethodDefinition: # new in 1.53 + Enabled: true +Style/SafeNavigationChainLength: # new in 1.68 + Enabled: true +Style/SendWithLiteralMethodName: # new in 1.64 + Enabled: true +Style/SingleLineDoEndBlock: # new in 1.57 + Enabled: true +Style/SuperArguments: # new in 1.64 + Enabled: true +Style/SuperWithArgsParentheses: # new in 1.58 + Enabled: true +Style/YAMLFileRead: # new in 1.53 + Enabled: true \ No newline at end of file diff --git a/berkeley_library-util.gemspec b/berkeley_library-util.gemspec index 588de8c..74a7438 100644 --- a/berkeley_library-util.gemspec +++ b/berkeley_library-util.gemspec @@ -2,7 +2,7 @@ File.expand_path('lib', __dir__).tap do |lib| $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) end -ruby_version = '>= 2.7' +ruby_version = '~> 3.3' require 'berkeley_library/util/module_info' @@ -21,19 +21,19 @@ Gem::Specification.new do |spec| spec.required_ruby_version = ruby_version - spec.add_dependency 'berkeley_library-logging', '~> 0.2' + spec.add_dependency 'berkeley_library-logging', '~> 0.3' spec.add_dependency 'rest-client', '~> 2.1' spec.add_dependency 'typesafe_enum', '~> 0.3' spec.add_development_dependency 'ci_reporter_rspec', '~> 1.0' - spec.add_development_dependency 'colorize', '~> 0.8' + spec.add_development_dependency 'colorize', '~> 1.0' spec.add_development_dependency 'dotenv', '~> 2.7' spec.add_development_dependency 'rake', '~> 13.0' spec.add_development_dependency 'rspec', '~> 3.10' - spec.add_development_dependency 'rubocop', '= 1.39' - spec.add_development_dependency 'rubocop-rake', '= 0.6.0' - spec.add_development_dependency 'rubocop-rspec', '= 2.4.0' - spec.add_development_dependency 'ruby-prof', '~> 0.17.0' + spec.add_development_dependency 'rubocop', '~> 1.78.0' + spec.add_development_dependency 'rubocop-rake', '~> 0.7.1' + spec.add_development_dependency 'rubocop-rspec', '~> 3.6.0' + spec.add_development_dependency 'ruby-prof' spec.add_development_dependency 'simplecov', '~> 0.21' spec.add_development_dependency 'webmock', '~> 3.12' diff --git a/rakelib/.rubocop.yml b/rakelib/.rubocop.yml index 93dfdb7..49c83db 100644 --- a/rakelib/.rubocop.yml +++ b/rakelib/.rubocop.yml @@ -1,4 +1,4 @@ inherit_from: ../.rubocop.yml -require: +plugins: - rubocop-rake diff --git a/spec/.rubocop.yml b/spec/.rubocop.yml index 37c5923..c540a42 100644 --- a/spec/.rubocop.yml +++ b/spec/.rubocop.yml @@ -1,6 +1,6 @@ inherit_from: ../.rubocop.yml -require: +plugins: - rubocop-rspec AllCops: @@ -78,9 +78,12 @@ RSpec/ExpectInHook: Enabled: false # your naming scheme is not in possession of all the facts -RSpec/FilePath: +RSpec/SpecFilePathFormat: Enabled: false +RSpec/SpecFilePathSuffix: + Enabled: true + # explicit >>> implicit RSpec/InstanceVariable: Enabled: false @@ -125,5 +128,3 @@ RSpec/VerifiedDoubles: RSpec/IdenticalEqualityAssertion: # new in 2.4 Enabled: true -RSpec/Rails/AvoidSetupHook: # new in 2.4 - Enabled: true From 70c9d4a2c8c9d124b5fcca292a6e1b717420f2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mar=C3=ADa=20a=2E=20matienzo?= Date: Thu, 24 Jul 2025 09:03:58 -0700 Subject: [PATCH 2/6] add docker/compose configs for gem testing/building --- Dockerfile | 58 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 13 +++++++++++ 2 files changed, 71 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d2488bc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,58 @@ +# ============================================================================= +# Target: base + +FROM ruby:3.3-alpine AS base + +RUN apk --no-cache --update upgrade && \ + apk --no-cache add \ + bash \ + ca-certificates \ + git \ + libc6-compat \ + openssl \ + tzdata \ + xz-libs \ + yaml-dev \ + && rm -rf /var/cache/apk/* + +WORKDIR /opt/app + +# ============================================================================= +# Target: development +# + +FROM base AS development + +# Install system packages needed to build gems with C extensions. +RUN apk --update --no-cache add \ + build-base \ + coreutils \ + git \ + && rm -rf /var/cache/apk/* + +# The base image ships an older bundler, but we want something more recent +RUN gem install bundler -v 2.5.22 + +# Copy codebase to WORKDIR. Unlike application projects, for a gem project +# we need to do this before running `bundle install`, in order for the gem +# we're building to be able to "install" itself. +COPY . . + +# Install gems. +RUN bundle install --path=/usr/local/bundle + +# ============================================================================= +# Target: production + +FROM base AS production + +# Copy the built codebase from the dev stage +COPY --from=development /opt/app /opt/app +COPY --from=development /usr/local/bundle /usr/local/bundle + +# Sanity-check that everything was installed correctly and still runs in the +# slimmed-down production image. +RUN bundle config set deployment 'true' +RUN bundle install --local --path=/usr/local/bundle + +CMD ["bundle", "exec", "rake"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6c9b58e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +services: + gem: + build: + context: . + target: development + ports: + - target: 3000 + published: 3000 + restart: always + volumes: + # Note that this mounts the *entire* repo directory (including + # files ignored in .dockerignore when building the image) + - ./:/opt/app \ No newline at end of file From 4ba55cb046b9b8817273dbebdbd177160edfc499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mar=C3=ADa=20a=2E=20matienzo?= Date: Thu, 24 Jul 2025 09:09:51 -0700 Subject: [PATCH 3/6] rubocop fixes --- lib/berkeley_library/util/arrays.rb | 2 +- lib/berkeley_library/util/strings.rb | 2 +- lib/berkeley_library/util/uris.rb | 12 +++---- spec/berkeley_library/util/arrays_spec.rb | 34 +++++++++--------- spec/berkeley_library/util/files_spec.rb | 40 +++++++++++----------- spec/berkeley_library/util/strings_spec.rb | 6 ++-- 6 files changed, 46 insertions(+), 50 deletions(-) diff --git a/lib/berkeley_library/util/arrays.rb b/lib/berkeley_library/util/arrays.rb index f621969..11d893e 100644 --- a/lib/berkeley_library/util/arrays.rb +++ b/lib/berkeley_library/util/arrays.rb @@ -142,7 +142,7 @@ def do_merge(shorter, longer) shorter_unmatched = shorter[0...ix_s] longer_unmatched = longer[0...ix_l] all_unmatched = sort_by_first_and_flatten(shorter_unmatched, longer_unmatched) - return (all_unmatched << v) + merge(shorter[ix_s + 1..], longer[ix_l + 1..]) + return (all_unmatched << v) + merge(shorter[(ix_s + 1)..], longer[(ix_l + 1)..]) end sort_by_first_and_flatten(longer, shorter) diff --git a/lib/berkeley_library/util/strings.rb b/lib/berkeley_library/util/strings.rb index 7c0618f..f67e4b8 100644 --- a/lib/berkeley_library/util/strings.rb +++ b/lib/berkeley_library/util/strings.rb @@ -8,7 +8,7 @@ module Strings def ascii_numeric?(s) s.chars.all? do |c| ord = c.ord - ord >= ASCII_0 && ord <= ASCII_9 + ord.between?(ASCII_0, ASCII_9) end end diff --git a/lib/berkeley_library/util/uris.rb b/lib/berkeley_library/util/uris.rb index 2b3b545..a06ae4f 100644 --- a/lib/berkeley_library/util/uris.rb +++ b/lib/berkeley_library/util/uris.rb @@ -109,14 +109,14 @@ def safe_parse_uri(url) nil end - private - # TODO: extend to cover other modes - host, zone, path, password, query, fragment # cf. https://github.com/golang/go/blob/master/src/net/url/url.go ALLOWED_BYTES_BY_MODE = { path_segment: [0x24, 0x26, 0x2b, 0x3a, 0x3d, 0x40] # @ & = + $ }.freeze + private + def should_escape?(b, mode) return false if unreserved?(b) return false if ALLOWED_BYTES_BY_MODE[mode].include?(b) @@ -124,16 +124,14 @@ def should_escape?(b, mode) true end - # rubocop:disable Metrics/CyclomaticComplexity def unreserved?(byte) - return true if byte >= 0x41 && byte <= 0x5a # A-Z - return true if byte >= 0x61 && byte <= 0x7a # a-z - return true if byte >= 0x30 && byte <= 0x39 # 0-9 + return true if byte.between?(0x41, 0x5a) # A-Z + return true if byte.between?(0x61, 0x7a) # a-z + return true if byte.between?(0x30, 0x39) # 0-9 return true if [0x2d, 0x2e, 0x5f, 0x7e].include?(byte) # - . _ ~ false end - # rubocop:enable Metrics/CyclomaticComplexity end end end diff --git a/spec/berkeley_library/util/arrays_spec.rb b/spec/berkeley_library/util/arrays_spec.rb index 7b8893c..82754ec 100644 --- a/spec/berkeley_library/util/arrays_spec.rb +++ b/spec/berkeley_library/util/arrays_spec.rb @@ -8,11 +8,11 @@ module BerkeleyLibrary::Util let(:sup) { %w[a b c d e] } it 'returns true for an identical subset' do - expect(Arrays.ordered_superset?(superset: sup, subset: sup.dup)).to eq(true) + expect(Arrays.ordered_superset?(superset: sup, subset: sup.dup)).to be(true) end it 'returns true for an empty subset' do - expect(Arrays.ordered_superset?(superset: sup, subset: [])).to eq(true) + expect(Arrays.ordered_superset?(superset: sup, subset: [])).to be(true) end it 'returns true for an exact sublist' do @@ -22,7 +22,7 @@ module BerkeleyLibrary::Util %w[c d e] ] subs.each do |sub| - expect(Arrays.ordered_superset?(superset: sup, subset: sub)).to eq(true) + expect(Arrays.ordered_superset?(superset: sup, subset: sub)).to be(true) end end @@ -33,13 +33,13 @@ module BerkeleyLibrary::Util %w[a b d e] ] subs.each do |sub| - expect(Arrays.ordered_superset?(superset: sup, subset: sub)).to eq(true) + expect(Arrays.ordered_superset?(superset: sup, subset: sub)).to be(true) end end it 'returns false for a too-large subset' do sub = %w[a b c d e f g] - expect(Arrays.ordered_superset?(superset: sup, subset: sub)).to eq(false) + expect(Arrays.ordered_superset?(superset: sup, subset: sub)).to be(false) end it 'returns false when extra elements are present' do @@ -49,7 +49,7 @@ module BerkeleyLibrary::Util %w[c d x e] ] subs.each do |sub| - expect(Arrays.ordered_superset?(superset: sup, subset: sub)).to eq(false) + expect(Arrays.ordered_superset?(superset: sup, subset: sub)).to be(false) end end end @@ -150,7 +150,6 @@ module BerkeleyLibrary::Util expect { Arrays.find_index(1, 2, 3, in_array: [1, 2, 3]) }.to raise_error(ArgumentError) end - # rubocop:disable Lint/Void it 'returns an enumerator if given no arguments' do e = Arrays.find_index(in_array: arr) expect(e.each { |x| x > 3 }).to eq(2) @@ -158,7 +157,6 @@ module BerkeleyLibrary::Util e = Arrays.find_index(in_array: arr, start_index: 3) expect(e.each { |x| x < 5 }).to eq(4) end - # rubocop:enable Lint/Void end describe :merge do @@ -181,7 +179,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = [1, 2, 2, 3, 4, 4, 5, 5, 6] @@ -195,7 +193,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = [1, 2, 3, 4, 5, 7, 8, 9] @@ -209,7 +207,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = [1, 2, 3, 2, 2, 4] @@ -223,7 +221,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = [1, nil, 3, nil, nil, 4] @@ -237,7 +235,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = [1, 'two', 3, 'two', 'two', 4] @@ -251,7 +249,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = a2 @@ -267,7 +265,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = [1, 2, 3, 4, 5, 6, 9] @@ -283,7 +281,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = [1, 6, 9, 2, 3, 4, 5] @@ -299,7 +297,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end expected = [1, 2, 3, 4, 5, 6, 9] @@ -319,7 +317,7 @@ module BerkeleyLibrary::Util merged = Arrays.merge(a1, a2) [a1, a2].each do |a| - expect(Arrays.ordered_superset?(superset: merged, subset: a)).to eq(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" + expect(Arrays.ordered_superset?(superset: merged, subset: a)).to be(true), "merge(#{[a1.join, a2.join].inspect}): #{a.join} not found in #{merged.join}" end end end diff --git a/spec/berkeley_library/util/files_spec.rb b/spec/berkeley_library/util/files_spec.rb index 6987686..723ca8d 100644 --- a/spec/berkeley_library/util/files_spec.rb +++ b/spec/berkeley_library/util/files_spec.rb @@ -14,42 +14,42 @@ module Util describe :file_exists? do it 'returns true for files that exist' do path = Pathname.new(tmpdir).join('exists').tap { |p| FileUtils.touch(p) } - expect(path.exist?).to eq(true) # just to be sure + expect(path.exist?).to be(true) # just to be sure path_str = path.to_s - expect(Files.file_exists?(path)).to eq(true) - expect(Files.file_exists?(path_str)).to eq(true) + expect(Files.file_exists?(path)).to be(true) + expect(Files.file_exists?(path_str)).to be(true) end it 'returns false for files that do not exist' do path = Pathname.new(tmpdir).join('not-exists') - expect(path.exist?).to eq(false) # just to be sure + expect(path.exist?).to be(false) # just to be sure path_str = path.to_s - expect(Files.file_exists?(path)).to eq(false) - expect(Files.file_exists?(path_str)).to eq(false) + expect(Files.file_exists?(path)).to be(false) + expect(Files.file_exists?(path_str)).to be(false) end end describe :parent_exists? do it 'returns true for paths whose parent exists' do parent = Pathname.new(tmpdir).join('parent').tap(&:mkdir) - expect(parent.exist?).to eq(true) # just to be sure + expect(parent.exist?).to be(true) # just to be sure path = parent.join('child') path_str = path.to_s - expect(Files.parent_exists?(path)).to eq(true) - expect(Files.parent_exists?(path_str)).to eq(true) + expect(Files.parent_exists?(path)).to be(true) + expect(Files.parent_exists?(path_str)).to be(true) end it 'returns false for paths whose parent does not' do parent = Pathname.new(tmpdir).join('parent') - expect(parent.exist?).to eq(false) # just to be sure + expect(parent.exist?).to be(false) # just to be sure path = parent.join('child') path_str = path.to_s - expect(Files.parent_exists?(path)).to eq(false) - expect(Files.parent_exists?(path_str)).to eq(false) + expect(Files.parent_exists?(path)).to be(false) + expect(Files.parent_exists?(path_str)).to be(false) end end @@ -59,19 +59,19 @@ module Util FileUtils.touch(filename) File.open(filename, 'rb') do |out| - expect(Files.reader_like?(out)).to eq(true) + expect(Files.reader_like?(out)).to be(true) end end it 'returns true for a StringIO' do out = StringIO.new - expect(Files.reader_like?(out)).to eq(true) + expect(Files.reader_like?(out)).to be(true) end it 'returns true for a Tempfile' do out = Tempfile.new('out') begin - expect(Files.reader_like?(out)).to eq(true) + expect(Files.reader_like?(out)).to be(true) ensure out.close out.unlink @@ -79,7 +79,7 @@ module Util end it 'returns false for something that is not reader-like' do - expect(Files.reader_like?('not an IO')).to eq(false) + expect(Files.reader_like?('not an IO')).to be(false) end end @@ -88,19 +88,19 @@ module Util filename = File.join(tmpdir, 'out') File.open(filename, 'wb') do |out| - expect(Files.writer_like?(out)).to eq(true) + expect(Files.writer_like?(out)).to be(true) end end it 'returns true for a StringIO' do out = StringIO.new - expect(Files.writer_like?(out)).to eq(true) + expect(Files.writer_like?(out)).to be(true) end it 'returns true for a Tempfile' do out = Tempfile.new('out') begin - expect(Files.writer_like?(out)).to eq(true) + expect(Files.writer_like?(out)).to be(true) ensure out.close out.unlink @@ -108,7 +108,7 @@ module Util end it 'returns false for something that is not writer-like' do - expect(Files.writer_like?('not an IO')).to eq(false) + expect(Files.writer_like?('not an IO')).to be(false) end end end diff --git a/spec/berkeley_library/util/strings_spec.rb b/spec/berkeley_library/util/strings_spec.rb index 96d36bf..79f0cf5 100644 --- a/spec/berkeley_library/util/strings_spec.rb +++ b/spec/berkeley_library/util/strings_spec.rb @@ -6,7 +6,7 @@ module Util describe :ascii_numeric do it 'returns true for ASCII numeric strings' do str = '8675309' - expect(Strings.ascii_numeric?(str)).to eq(true) + expect(Strings.ascii_numeric?(str)).to be(true) end it 'returns false for non-ASCII numeric strings' do @@ -16,7 +16,7 @@ module Util ] aggregate_failures 'non-ASCII numeric strings' do strs.each do |str| - expect(Strings.ascii_numeric?(str)).to eq(false), "Expected #{str.inspect} to be non-ASCII-numeric" + expect(Strings.ascii_numeric?(str)).to be(false), "Expected #{str.inspect} to be non-ASCII-numeric" end end end @@ -29,7 +29,7 @@ module Util ] aggregate_failures 'ASCII mixed numeric and non-numeric strings' do strs.each do |str| - expect(Strings.ascii_numeric?(str)).to eq(false), "Expected #{str.inspect} to be non-ASCII-numeric" + expect(Strings.ascii_numeric?(str)).to be(false), "Expected #{str.inspect} to be non-ASCII-numeric" end end end From 592475633bff3cae15c00deb3bd37d74203c07e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mar=C3=ADa=20a=2E=20matienzo?= Date: Thu, 24 Jul 2025 09:16:10 -0700 Subject: [PATCH 4/6] prep release, update build workflows --- .github/workflows/build.yml | 6 ++--- .github/workflows/gem-push.yml | 33 ++++++++++++++++++++++++ berkeley_library-util.gemspec | 4 +-- lib/berkeley_library/util/module_info.rb | 6 ++--- 4 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/gem-push.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c4c1e0..57f80f7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, macos-latest ] - ruby: [ '2.7', '3.0', '3.1' ] + ruby: [ '3.3', '3.4' ] runs-on: ${{ matrix.os }} steps: @@ -24,7 +24,7 @@ jobs: - name: Upload artifacts if: ${{ always() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: artifacts + name: artifacts-${{ matrix.ruby }}-${{ matrix.os }} path: artifacts/** diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml new file mode 100644 index 0000000..d82bddd --- /dev/null +++ b/.github/workflows/gem-push.yml @@ -0,0 +1,33 @@ +name: Ruby Gem + +on: + release: + types: [published] + +jobs: + build: + name: Build + Publish + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v3 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + + - name: Publish to RubyGems + run: | + mkdir -p $HOME/.gem + touch $HOME/.gem/credentials + chmod 0600 $HOME/.gem/credentials + printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials + gem build *.gemspec + gem push *.gem + env: + GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}" \ No newline at end of file diff --git a/berkeley_library-util.gemspec b/berkeley_library-util.gemspec index 74a7438..6c592a5 100644 --- a/berkeley_library-util.gemspec +++ b/berkeley_library-util.gemspec @@ -8,8 +8,8 @@ require 'berkeley_library/util/module_info' Gem::Specification.new do |spec| spec.name = BerkeleyLibrary::Util::ModuleInfo::NAME - spec.author = BerkeleyLibrary::Util::ModuleInfo::AUTHOR - spec.email = BerkeleyLibrary::Util::ModuleInfo::AUTHOR_EMAIL + spec.author = BerkeleyLibrary::Util::ModuleInfo::AUTHORS + spec.email = BerkeleyLibrary::Util::ModuleInfo::AUTHOR_EMAILS spec.summary = BerkeleyLibrary::Util::ModuleInfo::SUMMARY spec.description = BerkeleyLibrary::Util::ModuleInfo::DESCRIPTION spec.license = BerkeleyLibrary::Util::ModuleInfo::LICENSE diff --git a/lib/berkeley_library/util/module_info.rb b/lib/berkeley_library/util/module_info.rb index 7938f5e..3dc1362 100644 --- a/lib/berkeley_library/util/module_info.rb +++ b/lib/berkeley_library/util/module_info.rb @@ -2,12 +2,12 @@ module BerkeleyLibrary module Util class ModuleInfo NAME = 'berkeley_library-util'.freeze - AUTHOR = 'David Moles'.freeze - AUTHOR_EMAIL = 'dmoles@berkeley.edu'.freeze + AUTHORS = ['David Moles', 'marĂ­a a. matienzo'].freeze + AUTHOR_EMAILS = ['dmoles@berkeley.edu', 'matienzo@berkeley.edu'].freeze SUMMARY = 'Miscellaneous Ruby utilities for the UC Berkeley Library'.freeze DESCRIPTION = 'A collection of miscellaneous Ruby routines for the UC Berkeley Library.'.freeze LICENSE = 'MIT'.freeze - VERSION = '0.1.9'.freeze + VERSION = '0.2.0'.freeze HOMEPAGE = 'https://github.com/BerkeleyLibrary/util'.freeze end end From af31c2ce1525bedb8ff4a7bc4f1f32498416abd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mar=C3=ADa=20a=2E=20matienzo?= Date: Thu, 24 Jul 2025 11:47:50 -0700 Subject: [PATCH 5/6] address PR feedback --- .github/workflows/gem-push.yml | 2 +- docker-compose.yml | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index d82bddd..9e6341e 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -30,4 +30,4 @@ jobs: gem build *.gemspec gem push *.gem env: - GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}" \ No newline at end of file + GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}" diff --git a/docker-compose.yml b/docker-compose.yml index 6c9b58e..b296278 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,11 +3,8 @@ services: build: context: . target: development - ports: - - target: 3000 - published: 3000 restart: always volumes: # Note that this mounts the *entire* repo directory (including # files ignored in .dockerignore when building the image) - - ./:/opt/app \ No newline at end of file + - ./:/opt/app From 44e004d4b66e98e926f5b4280cbc335b57a3cb50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mar=C3=ADa=20a=2E=20matienzo?= Date: Thu, 24 Jul 2025 11:52:09 -0700 Subject: [PATCH 6/6] update changelog --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index b159d71..df4c001 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,8 @@ +# 0.2.0 (2025-07-24) + +- Update to support Ruby 3.3+. +- Update Rubocop & style changes. + # 0.1.9 (2023-06-01) - `URIs#path_escape` now attempts to convert non-UTF-8 strings to UTF-8 rather than immediately