From 4c531a3762ceb0696fb36cb8f2d0a2f6027077c5 Mon Sep 17 00:00:00 2001
From: Paul DobbinSchmaltz
Date: Fri, 22 Nov 2024 11:04:45 -0600
Subject: [PATCH] Add GitHub Actions + bump.rake to maintain ruby versions
Using bump.rake also necessitated renaming MIT-LICENSE to LICENSE.txt,
for uniformity with my other gems that use this same rake file.
---
.github/workflows/ci.yml | 52 +++++++++++++++++++
Gemfile.lock | 2 +-
LICENSE.txt | 21 ++++++++
MIT-LICENSE | 20 --------
rakelib/bump.rake | 106 +++++++++++++++++++++++++++++++++++++++
5 files changed, 180 insertions(+), 21 deletions(-)
create mode 100644 .github/workflows/ci.yml
create mode 100644 LICENSE.txt
delete mode 100644 MIT-LICENSE
create mode 100644 rakelib/bump.rake
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..78e2763
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,52 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
+# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
+
+name: CI
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: read
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ ruby-version: ["3.1", "3.2", "3.3"]
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby-version }}
+ bundler-cache: true # runs `bundle install` and caches installed gems automatically
+
+ - name: Run tests
+ run: bundle exec rake test
+
+ rubocop:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "3.3.6"
+ bundler-cache: true # runs `bundle install` and caches installed gems automatically
+
+ - name: Run rubocop
+ run: bundle exec rubocop
diff --git a/Gemfile.lock b/Gemfile.lock
index 41798b5..15225c1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -286,4 +286,4 @@ DEPENDENCIES
statusable!
BUNDLED WITH
- 2.3.27
+ 2.5.23
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..105e3a9
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2024 Paul DobbinSchmaltz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/MIT-LICENSE b/MIT-LICENSE
deleted file mode 100644
index 6e2e504..0000000
--- a/MIT-LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright Paul DobbinSchmaltz
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/rakelib/bump.rake b/rakelib/bump.rake
new file mode 100644
index 0000000..6c2ad21
--- /dev/null
+++ b/rakelib/bump.rake
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require "date"
+require "open-uri"
+require "yaml"
+
+desc "Update Bundler version, Ruby version, and LICENSE year in relevant files"
+task :bump do
+ run_tasks(%w[
+ bump:bundler
+ bump:ruby
+ bump:year
+ ])
+end
+
+namespace :bump do
+ desc "Update Bundler version to latest in Gemfile.lock"
+ task :bundler do
+ version = Gem.latest_version_for("bundler").to_s
+ replace_in_file("Gemfile.lock", /^BUNDLED WITH\n\s+(\d\S+)$/ => version)
+ end
+
+ desc "Update Ruby version targets in relevant files"
+ task :ruby do
+ replace_in_file(
+ "statusable.gemspec",
+ /ruby_version = .*">= (.*)"/ => RubyVersions.lowest_supported_minor)
+ replace_in_file(
+ ".rubocop.yml",
+ /TargetRubyVersion: (.*)/ => RubyVersions.lowest_supported_minor)
+ replace_in_file(
+ ".github/workflows/ci.yml",
+ /ruby-version: "([\d.]+)"/ => RubyVersions.latest)
+ replace_in_file(
+ ".github/workflows/ci.yml",
+ /ruby-version: (\[(?:"[\d.]+"(?:, )?)*\])/ =>
+ RubyVersions.latest_supported_minors.to_s)
+ end
+
+ desc "Update year to current in LICENSE.txt"
+ task :year do
+ replace_in_file("LICENSE.txt", /\(c\) (\d+)/ => Date.today.year.to_s)
+ end
+end
+
+def replace_in_file(path, replacements)
+ file_contents = File.read(path)
+ original_file_contents = file_contents.dup
+
+ replacements.each do |regex, text|
+ raise "Can't find #{regex} in #{path}" unless regex.match?(file_contents)
+
+ file_contents.gsub!(regex) do |match|
+ match[regex, 1] = text
+ match
+ end
+ end
+
+ File.write(path, file_contents) if file_contents != original_file_contents
+end
+
+# RubyVersions extracts current Ruby versions info from
+# https://raw.githubusercontent.com/ruby/www.ruby-lang.org/HEAD/_data/downloads.yml
+# -- which specifies the Ruby releases that will be listed on
+# https://www.ruby-lang.org/en/downloads/
+module RubyVersions
+ MINOR_VERSION_REGEX = /\d+\.\d+/
+ RUBY_VERSIONS_YAML_PATH =
+ "https://raw.githubusercontent.com/ruby/www.ruby-lang.org/HEAD/_data/downloads.yml"
+ VERSION_TYPES = %i[
+ security_maintenance
+ stable
+ ].freeze
+
+ def self.latest
+ latest_supported_patches.last
+ end
+
+ def self.latest_supported_minors
+ latest_supported_patches.map { |version_string|
+ version_string[MINOR_VERSION_REGEX]
+ }
+ end
+
+ def self.latest_supported_patches
+ @latest_supported_patches ||= begin
+ patches =
+ versions.fetch_values(*VERSION_TYPES).tap(&:flatten!).tap(&:compact!)
+ patches.map { |patch| Gem::Version.new(patch) }.sort!.map(&:to_s)
+ end
+ end
+
+ def self.lowest_supported_minor
+ latest_supported_patches.first[MINOR_VERSION_REGEX]
+ end
+
+ private
+
+ def self.versions
+ @versions ||= begin
+ raw_yaml = URI.parse(RUBY_VERSIONS_YAML_PATH).open
+ YAML.safe_load(raw_yaml, symbolize_names: true)
+ end
+ end
+ private_class_method :versions
+end