From 0560c24a8776b0736f67d1b5a6274ca29d7563d1 Mon Sep 17 00:00:00 2001 From: Patrick Macklin Date: Mon, 3 Aug 2026 09:27:39 -0500 Subject: [PATCH 1/2] feat[INFRA-1189]: publish gem to JFrog with GHA release Add date-based release:publish to release-gems, modernize RSpec CI, and document he-gems install. Co-authored-by: Cursor --- .github/workflows/release.yml | 31 +++ .github/workflows/verify.yml | 26 ++ .gitignore | 4 +- .ruby-version | 2 +- .travis.yml | 15 -- Gemfile | 12 +- Gemfile.lock | 252 ++++++++++++++++++ README.md | 28 +- Rakefile | 184 ++++++++++++- google_visualr.gemspec | 18 +- lib/google_visualr/version.rb | 8 +- .../app/controllers/application_controller.rb | 3 +- spec/dummy/config/application.rb | 37 +-- spec/dummy/config/boot.rb | 7 +- spec/dummy/config/environment.rb | 6 +- spec/dummy/config/environments/test.rb | 38 +-- spec/dummy/config/routes.rb | 58 +--- spec/google_visualr/data_table_spec.rb | 2 +- spec/spec_helper.rb | 18 +- 19 files changed, 572 insertions(+), 177 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/verify.yml delete mode 100644 .travis.yml create mode 100644 Gemfile.lock diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..8951f3b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,31 @@ +name: Release + +on: + workflow_dispatch: + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + env: + BUNDLE_HOTELENGINE__JFROG__IO: "${{ github.actor == 'dependabot[bot]' && 'dependabot' || vars.JF_USER }}:${{ secrets.JF_PASSWORD }}" + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + fetch-tags: 'true' + fetch-depth: '0' + + - name: Set up Ruby + uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0 + with: + ruby-version: '3.2' + bundler-cache: true + + - name: Publish + run: bundle exec rake release:publish + env: + JF_NPM_TOKEN: ${{ secrets.JF_NPM_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 0000000..1218e04 --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,26 @@ +name: Verify + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + strategy: + fail-fast: false + matrix: + ruby: + - "3.2" + - "3.3" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Ruby ${{ matrix.ruby }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run specs + run: bundle exec rspec diff --git a/.gitignore b/.gitignore index 5d4f69c..cd84680 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ pkg/* .bundle .idea vendor/bundle -/Gemfile.lock + +# Build artifact: version is derived from git describe at release time. +/lib/google_visualr/version.txt diff --git a/.ruby-version b/.ruby-version index 378bc55..e650c01 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-2.1.3 +3.2.9 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a035227..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: ruby -bundler_args: --retry=3 --jobs=3 --no-deployment -cache: bundler -sudo: false - -rvm: - - 2.0.0 - - 2.1.6 - - 2.2.2 - -gemfile: - - gemfiles/3.2.gemfile - - gemfiles/4.0.gemfile - - gemfiles/4.1.gemfile - - Gemfile diff --git a/Gemfile b/Gemfile index 4f940a0..c9d0a98 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,12 @@ +# frozen_string_literal: true + source "https://rubygems.org" gemspec -group :development do - gem "bundler", ">= 1.3.5" - gem "rspec", "~> 2.99.0" - gem "appraisal" - gem "rails", "~> 4.2.1" +group :development, :test do + gem "rake", "~> 13.0" + gem "rspec", "~> 3.13" + gem "rails", "~> 7.1" + gem "sqlite3", "~> 1.7" end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..5530bf4 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,252 @@ +PATH + remote: . + specs: + google_visualr (2026.07.28) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.2.3.1) + actionpack (= 7.2.3.1) + activesupport (= 7.2.3.1) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + zeitwerk (~> 2.6) + actionmailbox (7.2.3.1) + actionpack (= 7.2.3.1) + activejob (= 7.2.3.1) + activerecord (= 7.2.3.1) + activestorage (= 7.2.3.1) + activesupport (= 7.2.3.1) + mail (>= 2.8.0) + actionmailer (7.2.3.1) + actionpack (= 7.2.3.1) + actionview (= 7.2.3.1) + activejob (= 7.2.3.1) + activesupport (= 7.2.3.1) + mail (>= 2.8.0) + rails-dom-testing (~> 2.2) + actionpack (7.2.3.1) + actionview (= 7.2.3.1) + activesupport (= 7.2.3.1) + cgi + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4, < 3.3) + rack-session (>= 1.0.1) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + useragent (~> 0.16) + actiontext (7.2.3.1) + actionpack (= 7.2.3.1) + activerecord (= 7.2.3.1) + activestorage (= 7.2.3.1) + activesupport (= 7.2.3.1) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.2.3.1) + activesupport (= 7.2.3.1) + builder (~> 3.1) + cgi + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.2.3.1) + activesupport (= 7.2.3.1) + globalid (>= 0.3.6) + activemodel (7.2.3.1) + activesupport (= 7.2.3.1) + activerecord (7.2.3.1) + activemodel (= 7.2.3.1) + activesupport (= 7.2.3.1) + timeout (>= 0.4.0) + activestorage (7.2.3.1) + actionpack (= 7.2.3.1) + activejob (= 7.2.3.1) + activerecord (= 7.2.3.1) + activesupport (= 7.2.3.1) + marcel (~> 1.0) + activesupport (7.2.3.1) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1, < 6) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + base64 (0.3.0) + benchmark (0.5.0) + bigdecimal (4.1.2) + builder (3.3.0) + cgi (0.5.2) + concurrent-ruby (1.3.8) + connection_pool (3.0.2) + crass (1.0.7) + date (3.5.1) + diff-lcs (1.6.2) + drb (2.2.3) + erb (6.0.6) + erubi (1.13.1) + globalid (1.4.0) + activesupport (>= 6.1) + i18n (1.15.2) + concurrent-ruby (~> 1.0) + io-console (0.8.2) + irb (1.18.0) + pp (>= 0.6.0) + prism (>= 1.3.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + logger (1.7.0) + loofah (2.25.2) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.9.1) + logger + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.2.1) + mini_mime (1.1.5) + minitest (5.27.0) + net-imap (0.6.6) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.1) + net-protocol + nio4r (2.7.5) + nokogiri (1.19.4-aarch64-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.4-aarch64-linux-musl) + racc (~> 1.4) + nokogiri (1.19.4-arm-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.4-arm-linux-musl) + racc (~> 1.4) + nokogiri (1.19.4-arm64-darwin) + racc (~> 1.4) + nokogiri (1.19.4-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.19.4-x86_64-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.4-x86_64-linux-musl) + racc (~> 1.4) + pp (0.6.4) + prettyprint + prettyprint (0.2.0) + prism (1.9.0) + racc (1.8.1) + rack (3.2.6) + rack-session (2.1.2) + base64 (>= 0.1.0) + rack (>= 3.0.0) + rack-test (2.2.0) + rack (>= 1.3) + rackup (2.3.1) + rack (>= 3) + rails (7.2.3.1) + actioncable (= 7.2.3.1) + actionmailbox (= 7.2.3.1) + actionmailer (= 7.2.3.1) + actionpack (= 7.2.3.1) + actiontext (= 7.2.3.1) + actionview (= 7.2.3.1) + activejob (= 7.2.3.1) + activemodel (= 7.2.3.1) + activerecord (= 7.2.3.1) + activestorage (= 7.2.3.1) + activesupport (= 7.2.3.1) + bundler (>= 1.15.0) + railties (= 7.2.3.1) + rails-dom-testing (2.3.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.7.1) + loofah (~> 2.25, >= 2.25.2) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) + railties (7.2.3.1) + actionpack (= 7.2.3.1) + activesupport (= 7.2.3.1) + cgi + irb (~> 1.13) + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + tsort (>= 0.2) + zeitwerk (~> 2.6) + rake (13.4.2) + rbs (4.1.0) + logger + prism (>= 1.6.0) + tsort + rdoc (8.0.0) + erb + prism (>= 1.6.0) + rbs (>= 4.0.0) + tsort + reline (0.6.3) + io-console (~> 0.5) + rspec (3.13.2) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.6) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.8) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.7) + securerandom (0.4.1) + sqlite3 (1.7.3-aarch64-linux) + sqlite3 (1.7.3-arm-linux) + sqlite3 (1.7.3-arm64-darwin) + sqlite3 (1.7.3-x86_64-darwin) + sqlite3 (1.7.3-x86_64-linux) + thor (1.5.0) + timeout (0.6.1) + tsort (0.2.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + useragent (0.16.11) + websocket-driver (0.8.2) + base64 + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + zeitwerk (2.8.2) + +PLATFORMS + aarch64-linux + aarch64-linux-gnu + aarch64-linux-musl + arm-linux + arm-linux-gnu + arm-linux-musl + arm64-darwin + x86_64-darwin + x86_64-linux + x86_64-linux-gnu + x86_64-linux-musl + +DEPENDENCIES + google_visualr! + rails (~> 7.1) + rake (~> 13.0) + rspec (~> 3.13) + sqlite3 (~> 1.7) + +BUNDLED WITH + 2.7.2 diff --git a/README.md b/README.md index d4f8e5c..a2b28a7 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,8 @@ # GoogleVisualr -[![Gem Version](http://img.shields.io/gem/v/google_visualr.svg?style=flat-square)](https://rubygems.org/gems/google_visualr) -[![Build Status](http://img.shields.io/travis/winston/google_visualr.svg?style=flat-square)](https://travis-ci.org/winston/google_visualr) -[![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](https://github.com/winston/google_visualr/blob/master/MIT-LICENSE) +[![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](https://github.com/HotelEngine/google_visualr/blob/main/MIT-LICENSE) -GoogleVisualr, is a wrapper around the [Google Charts](https://developers.google.com/chart/) that allows anyone to create beautiful charts with just plain Ruby. You don't have to write any JavaScript at all. - -It's good for any Ruby (Rails/Sinatra) setup, and you can handle the entire charting logic in Ruby. +HotelEngine fork of [winston/google_visualr](https://github.com/winston/google_visualr) — a wrapper around [Google Charts](https://developers.google.com/chart/) that lets you create charts in plain Ruby (no JavaScript required). Please refer to the [GoogleVisualr API Reference site](http://googlevisualr.herokuapp.com/) for a complete list of Google charts that you can create with GoogleVisualr. @@ -26,9 +22,25 @@ are not implemented because they feel more natural being written as JavaScript f ## Install -Assuming you are on Rails 3/4, include the gem in your Gemfile. +`google_visualr` is published to HotelEngine's internal JFrog Artifactory. Install it from the `he-gems` source. This requires JFrog credentials to be set in the bundler config or with an environment variable (see [CI Authentication](#ci-authentication)). + +```rb +source "https://hotelengine.jfrog.io/artifactory/api/gems/he-gems/" do + gem "google_visualr" +end +``` + +### CI Authentication + +Installing gems from the private JFrog `he-gems` source requires JFrog credentials. Bundler reads them from a host-specific environment variable derived from the source host: `BUNDLE_HOTELENGINE__JFROG__IO`. + +Set it to your JFrog `user:password` (or `user:identity_token`) pair, both locally and in CI (GitHub Actions / CircleCI): + +```sh +export BUNDLE_HOTELENGINE__JFROG__IO=":" +``` - gem "google_visualr", ">= 2.5" +This is consistent with how `coverdog` and `servicedog` authenticate to the same Artifactory instance. ## Basics diff --git a/Rakefile b/Rakefile index 36e30d4..7b4469e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,9 +1,185 @@ -# Bundler Gem Tasks -require 'bundler' -Bundler::GemHelper.install_tasks +# frozen_string_literal: true + +require "bundler" +require "fileutils" +require "open3" +require "rspec/core/rake_task" -require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) task test: :spec task default: :spec + +# Publish to the local deployment repo (release-gems), NOT the he-gems virtual +# repo. he-gems aggregates local + remote repos for *resolving/consuming* gems +# (that is the source consumers put in their Gemfile) and has no deployment +# target, so pushing to it returns 403 "No local repository was configured as +# local deployment repository". This mirrors antifraud-contracts, which resolves +# from the he-* virtual repos but publishes to the release-* local repos. +GEM_HOST = "https://hotelengine.jfrog.io/artifactory/api/gems/release-gems" +VERSION_FILE = File.join("lib", "google_visualr", "version.txt") + +# Helpers for the release tasks: tag discovery, idempotency checks, and git +# identity configuration. Kept as small, readable methods. +module ReleaseHelpers + module_function + + # The exact tag pointing at HEAD, or nil when HEAD is not tagged. + def head_tag + # capture3 discards stderr (the "no tag matches" message), matching the + # old `2>/dev/null`; a non-zero status means HEAD is not tagged. + out, _err, status = Open3.capture3("git", "describe", "--exact-match", "--tags", "HEAD") + return nil unless status.success? + + tag = out.strip + tag.empty? ? nil : tag + end + + # True when a tag (annotated or lightweight) with this name already exists. + def tag_exists?(tag) + system("git", "rev-parse", "--verify", "--quiet", "#{tag}^{}", out: File::NULL, err: File::NULL) + end + + # True when a GitHub release already exists for the tag. + def release_exists?(tag) + system("gh", "release", "view", tag, out: File::NULL, err: File::NULL) + end + + # Today's date tag (YYYY.MM.DD), with a .N suffix appended until unused. + def next_date_tag + base = Time.now.utc.strftime("%Y.%m.%d") + return base unless tag_exists?(base) + + n = 1 + n += 1 while tag_exists?("#{base}.#{n}") + "#{base}.#{n}" + end + + # The version string the gem will build with (git describe output). + def current_version + out, = Open3.capture2("git", "describe", "--tags") + out.strip + end + + # `sh` is only available inside Rake task blocks (via Rake::DSL), not in plain + # module methods, so use `system` with `exception: true` to fail loudly here. + # `git config` exits non-zero when a key is unset, so capture2's output (empty + # in that case) is what we key off of rather than the status. + def configure_git_identity + name, = Open3.capture2("git", "config", "user.name") + if name.strip.empty? + actor = ENV["GITHUB_ACTOR"].to_s.strip + actor = "HotelEngine CI" if actor.empty? + system("git", "config", "user.name", actor, exception: true) + end + + email, = Open3.capture2("git", "config", "user.email") + return unless email.strip.empty? + + system("git", "config", "user.email", "actions.ci@hotelengine.com", exception: true) + end +end + +namespace :release do # rubocop:disable Metrics/BlockLength + desc "Determine the release tag: reuse HEAD's tag if present, else create+push a date tag" + task :tag do + tag = ReleaseHelpers.head_tag + if tag + puts "Reusing existing tag on HEAD: #{tag}" + else + tag = ReleaseHelpers.next_date_tag + puts "Creating new tag: #{tag}" + sh "git", "tag", "-a", tag, "-m", tag + sh "git", "push", "origin", tag + end + end + + desc "Write the release tag version to #{VERSION_FILE}" + task :write_version do + # Prefer the exact tag on HEAD (set by release:tag) so version.txt holds a + # clean, valid Gem::Version like "2026.06.24" or "2026.06.24.1". Raw + # `git describe` output can include commit-distance suffixes + # (e.g. "2026.06.24-3-gabc1234") that are not valid Gem::Versions and would + # break `gem build` and consumers. + version = ReleaseHelpers.head_tag || ReleaseHelpers.current_version + File.write(VERSION_FILE, version) + puts "Wrote version #{version} to #{VERSION_FILE}" + end + + desc "Write ~/.gem/credentials for JFrog gem push" + task :credentials do + token = ENV.fetch("JF_NPM_TOKEN") + dir = File.join(Dir.home, ".gem") + FileUtils.mkdir_p(dir) + path = File.join(dir, "credentials") + File.write(path, ":hotelengine_artifactory: Basic #{token}\n") + FileUtils.chmod(0o600, path) + puts "Wrote #{path} (mode 0600)" + end + + desc "Build the gem" + task :build do + # release:write_version rewrites lib/google_visualr/version.txt, which changes + # the path gemspec's version. Under `bundle exec` the child process inherits + # RUBYOPT=-rbundler/setup + BUNDLE_GEMFILE and would re-run Bundler in frozen + # mode, aborting because the gemspec no longer matches Gemfile.lock. gem build + # does not need Bundler, so run it in a clean (unbundled) environment. + Bundler.with_unbundled_env do + sh "gem build google_visualr.gemspec" + end + end + + desc "Push the built gem to JFrog" + task :push do + gemfile = Dir["google_visualr-*.gem"].max_by { |f| File.mtime(f) } + raise "No built gem found" unless gemfile + + # Same reason as release:build: run outside the frozen Bundler env so the + # gem push subprocess does not trip the changed-gemspec lockfile check. + output, status = Bundler.with_unbundled_env do + Open3.capture2e( + "gem", "push", "--key", "hotelengine_artifactory", "--host", GEM_HOST, gemfile + ) + end + puts output + next if status.success? + + # Tolerate ONLY the idempotent "this version is already published" response + # (JFrog/Artifactory returns 409 Conflict for a duplicate gem) so re-runs are + # safe. Match specific phrases rather than the bare word "conflict" so that + # unrelated auth/network/server errors are not mistaken for a duplicate and + # still abort the release. + if output.match?(/already exists|repository already contains|409 conflict/i) + warn "Gem version already exists on JFrog; treating push as a no-op." + next + end + + raise "gem push to #{GEM_HOST} failed (exit #{status.exitstatus}); see output above." + end + + desc "Create the GitHub release for the current tag (skips if it already exists)" + task :github_release do + tag = ReleaseHelpers.head_tag || ReleaseHelpers.current_version + if ReleaseHelpers.release_exists?(tag) + puts "GitHub release for #{tag} already exists; skipping creation." + next + end + sh "gh", "release", "create", tag, "--title", tag, "--generate-notes" + end + + desc "Full release: tag, build, push to JFrog, and create the GitHub release" + task :publish do + # Every step is idempotent (tag reuse, duplicate-tolerant push, release skip), + # so we intentionally do NOT short-circuit on the GitHub release existing. + # A run that previously created the GitHub release but failed to land the gem + # in he-gems will re-attempt the push on the next run instead of being skipped. + ReleaseHelpers.configure_git_identity + + Rake::Task["release:tag"].invoke + Rake::Task["release:write_version"].invoke + Rake::Task["release:credentials"].invoke + Rake::Task["release:build"].invoke + Rake::Task["release:push"].invoke + Rake::Task["release:github_release"].invoke + end +end diff --git a/google_visualr.gemspec b/google_visualr.gemspec index 8ebbfbe..e890f02 100644 --- a/google_visualr.gemspec +++ b/google_visualr.gemspec @@ -1,19 +1,25 @@ -$:.push File.expand_path("../lib", __FILE__) +# frozen_string_literal: true -# Maintain your gem's version: -require "google_visualr/version" +require_relative "lib/google_visualr/version" Gem::Specification.new do |s| s.name = "google_visualr" - s.version = GoogleVisualr::VERSION + # GoogleVisualr::VERSION is derived from lib/google_visualr/version.txt, which is a + # build artifact written during release. When it is absent (local checkouts, + # CI dependency install before the release step) VERSION is "unknown", which is + # not a valid Gem::Version, so fall back to a placeholder. Real release builds + # write version.txt before `gem build`, so the packaged gem carries the date + # version. + s.version = GoogleVisualr::VERSION == "unknown" ? "0.0.0" : GoogleVisualr::VERSION s.authors = ["Winston Teo"] s.email = ["winston.yongwei+google_visualr@gmail.com"] - s.homepage = "https://github.com/winston/google_visualr" + s.homepage = "https://github.com/HotelEngine/google_visualr" s.summary = "A Ruby wrapper around the Google Chart Tools that allows anyone to create the same beautiful charts with just plain Ruby." s.description = "This Ruby gem, GoogleVisualr, is a wrapper around the Google Chart Tools that allows anyone to create the same beautiful charts with just Ruby; you don't have to write any JavaScript at all." s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.md"] s.test_files = Dir["spec/**/*"] - s.license = 'MIT' + s.license = "MIT" + s.required_ruby_version = ">= 3.1.0" end diff --git a/lib/google_visualr/version.rb b/lib/google_visualr/version.rb index 4f07b7a..9fe0463 100644 --- a/lib/google_visualr/version.rb +++ b/lib/google_visualr/version.rb @@ -1,3 +1,9 @@ +# frozen_string_literal: true + module GoogleVisualr - VERSION = "2.5.1" + VERSION = begin + File.read(File.join(__dir__, "version.txt")).strip + rescue StandardError + "unknown" + end end diff --git a/spec/dummy/app/controllers/application_controller.rb b/spec/dummy/app/controllers/application_controller.rb index e8065d9..7944f9f 100644 --- a/spec/dummy/app/controllers/application_controller.rb +++ b/spec/dummy/app/controllers/application_controller.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true + class ApplicationController < ActionController::Base - protect_from_forgery end diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb index 5c0d953..fbdba14 100644 --- a/spec/dummy/config/application.rb +++ b/spec/dummy/config/application.rb @@ -1,38 +1,17 @@ -require File.expand_path('../boot', __FILE__) +# frozen_string_literal: true -require 'rails/all' +require "rails" +require "action_controller/railtie" +require "action_view/railtie" Bundler.require require "google_visualr" module Dummy class Application < Rails::Application - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - - # Custom directories with classes and modules you want to be autoloadable. - # config.autoload_paths += %W(#{config.root}/extras) - - # Only load the plugins named here, in the order given (default is alphabetical). - # :all can be used as a placeholder for all plugins not explicitly named. - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - - # Activate observers that should always be running. - # config.active_record.observers = :cacher, :garbage_collector, :forum_observer - - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de - - # Configure the default encoding used in templates for Ruby 1.9. - config.encoding = "utf-8" - - # Configure sensitive parameters which will be filtered from the log file. - config.filter_parameters += [:password] + config.load_defaults 7.1 + config.eager_load = false + config.secret_key_base = "dummy_secret_key_base_for_google_visualr_specs_only" + config.active_support.deprecation = :stderr end end diff --git a/spec/dummy/config/boot.rb b/spec/dummy/config/boot.rb index 4489e58..5b865f6 100644 --- a/spec/dummy/config/boot.rb +++ b/spec/dummy/config/boot.rb @@ -1,6 +1,5 @@ -require 'rubygems' +# frozen_string_literal: true -# Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __dir__) -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) +require "bundler/setup" diff --git a/spec/dummy/config/environment.rb b/spec/dummy/config/environment.rb index 3da5eb9..fe49ece 100644 --- a/spec/dummy/config/environment.rb +++ b/spec/dummy/config/environment.rb @@ -1,5 +1,5 @@ -# Load the rails application -require File.expand_path('../application', __FILE__) +# frozen_string_literal: true + +require_relative "application" -# Initialize the rails application Dummy::Application.initialize! diff --git a/spec/dummy/config/environments/test.rb b/spec/dummy/config/environments/test.rb index ca83a46..0a86cf7 100644 --- a/spec/dummy/config/environments/test.rb +++ b/spec/dummy/config/environments/test.rb @@ -1,41 +1,9 @@ -Dummy::Application.configure do - # Settings specified here will take precedence over those in config/application.rb. - - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true +# frozen_string_literal: true - # Do not eager load code on boot. This avoids loading your whole application - # just for the purpose of running a single test. If you are using a tool that - # preloads Rails for running tests, you may have to set it to true. +Dummy::Application.configure do config.eager_load = false - - # Disable serving static files from the `/public` folder by default since - # Apache or NGINX already handles this. - if Rails.version >= "4.2.0" - config.serve_static_files = true - else - config.serve_static_assets = true - end - config.static_cache_control = "public, max-age=3600" - - # Show full error reports and disable caching. - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false - - # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false - - # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false - - # Tell Action Mailer not to deliver emails to the real world. - # The :test delivery method accumulates sent emails in the - # ActionMailer::Base.deliveries array. - config.action_mailer.delivery_method = :test - - # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr end diff --git a/spec/dummy/config/routes.rb b/spec/dummy/config/routes.rb index b20a20f..edf04d2 100644 --- a/spec/dummy/config/routes.rb +++ b/spec/dummy/config/routes.rb @@ -1,58 +1,4 @@ -Dummy::Application.routes.draw do - # The priority is based upon order of creation: - # first created -> highest priority. +# frozen_string_literal: true - # Sample of regular route: - # match 'products/:id' => 'catalog#view' - # Keep in mind you can assign values other than :controller and :action - - # Sample of named route: - # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase - # This route can be invoked with purchase_url(:id => product.id) - - # Sample resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Sample resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Sample resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Sample resource route with more complex sub-resources - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', :on => :collection - # end - # end - - # Sample resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end - - # You can have the root of your site routed with "root" - # just remember to delete public/index.html. - # root :to => "welcome#index" - - # See how all your routes lay out with "rake routes" - - # This is a legacy wild controller route that's not recommended for RESTful applications. - # Note: This route will make all actions in every controller accessible via GET requests. - # match ':controller(/:action(/:id(.:format)))' +Rails.application.routes.draw do end diff --git a/spec/google_visualr/data_table_spec.rb b/spec/google_visualr/data_table_spec.rb index ebac604..ba24a4a 100644 --- a/spec/google_visualr/data_table_spec.rb +++ b/spec/google_visualr/data_table_spec.rb @@ -208,7 +208,7 @@ def assert_raises_exception(col, value) it "accepts BigDecimal as number" do expect { - dt.set_cell(0, 1, BigDecimal.new(42)) + dt.set_cell(0, 1, BigDecimal(42)) }.to_not raise_exception end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 78e4487..fc0f592 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,11 +1,10 @@ -require 'rubygems' -require 'bundler/setup' +# frozen_string_literal: true + +require "bundler/setup" -# Configure Rails Environment ENV["RAILS_ENV"] = "test" -require File.expand_path("../dummy/config/environment.rb", __FILE__) +require File.expand_path("dummy/config/environment.rb", __dir__) -# Load Support Files Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } module JavaScriptHelper @@ -20,6 +19,11 @@ def normalize_javascript(input) end RSpec.configure do |config| - # some (optional) config here - include JavaScriptHelper + config.expect_with :rspec do |c| + c.syntax = [:should, :expect] + end + config.mock_with :rspec do |c| + c.syntax = [:should, :expect] + end + config.include JavaScriptHelper end From 0a5163f20681982ac97a8612f8a0fbf1ca4dbd7a Mon Sep 17 00:00:00 2001 From: Patrick Macklin Date: Mon, 3 Aug 2026 09:44:18 -0500 Subject: [PATCH 2/2] fix[INFRA-1189]: align lockfile and pin setup-ruby SHA Lock path gem at 0.0.0 to match the missing-version.txt gemspec fallback under bundler-cache, and pin ruby/setup-ruby (and checkout) by SHA in Verify. Co-authored-by: Cursor --- .github/workflows/verify.yml | 4 ++-- Gemfile.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 1218e04..af7670e 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -16,9 +16,9 @@ jobs: - "3.3" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Set up Ruby ${{ matrix.ruby }} - uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true diff --git a/Gemfile.lock b/Gemfile.lock index 5530bf4..6298e46 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - google_visualr (2026.07.28) + google_visualr (0.0.0) GEM remote: https://rubygems.org/