Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2 from alphagov/gem-version-comparison
Browse files Browse the repository at this point in the history
Gem version comparison
  • Loading branch information
PeterHattyar authored Dec 15, 2023
2 parents 3b7bcd1 + 3cffa49 commit 0b6e8be
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 25 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ source 'https://rubygems.org'

gem 'octokit'
gem 'webmock'
gem 'rake'

group :development, :test do
gem 'rspec'
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ GEM
faraday (>= 1, < 3)
sawyer (~> 0.9)
public_suffix (5.0.3)
rake (13.1.0)
rexml (3.2.6)
rspec (3.12.0)
rspec-core (~> 3.12.0)
Expand Down Expand Up @@ -45,6 +46,7 @@ PLATFORMS

DEPENDENCIES
octokit
rake
rspec
webmock

Expand Down
7 changes: 7 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require './lib/version_checker'

task default: %w[gem_release_alert]

task :gem_release_alert do
VersionChecker.new.print_version_discrepancies
end
55 changes: 46 additions & 9 deletions lib/version_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,59 @@ class HttpError < RuntimeError
end

class VersionChecker
def fetch_rubygems_version(gemname)
uri = URI("https://rubygems.org/api/v1/gems/#{gemname}.json")
def print_version_discrepancies
discrepancies_found = false

fetch_all_govuk_gemspecs.each do |gemspec|
rubygems_version = fetch_rubygems_version(gemspec.name)
unless gemspec.version == rubygems_version
discrepancies_found = true
puts "Version mismatch for '#{gemspec.name}':"
puts " Version on RubyGems: #{rubygems_version}"
puts " Version on GitHub: #{gemspec.version}"
end
end

unless discrepancies_found
puts "No discrepancies found!"
end
end

def fetch_all_govuk_gemspecs
uri = URI("https://docs.publishing.service.gov.uk/gems.json")
res = Net::HTTP.get_response(uri)

raise HttpError unless res.is_a?(Net::HTTPSuccess)

JSON.parse(res.body)
.map { |gem| fetch_gemspec(gem["app_name"]) }
.compact
end

def fetch_rubygems_version(gem_name)
uri = URI("https://rubygems.org/api/v1/gems/#{gem_name}.json")
res = Net::HTTP.get_response(uri)

raise HttpError unless res.is_a?(Net::HTTPSuccess)

parsed_json = JSON.parse(res.body)
parsed_json['version']
JSON.parse(res.body)['version']
end

def fetch_github_version(gemname)
payload = Octokit.contents("alphagov/#{gemname}", path: "lib/#{gemname}/version.rb")
Base64.decode64(payload[:content]).split('"')[1]
def fetch_gemspec(repo_name)
Dir.mktmpdir do |path|
Dir.chdir(path) do
clone_github_repo(repo_name)
gemspecs = Dir.glob("*.gemspec", base: repo_name)
if gemspecs.count == 1
Gem::Specification::load("#{repo_name}/#{gemspecs.first}")
else
nil
end
end
end
end

def rubygems_and_github_match?(gemname)
fetch_rubygems_version(gemname) == fetch_github_version(gemname)
def clone_github_repo(name)
`git clone --recursive --depth 1 --shallow-submodules git@github.com:alphagov/#{name}.git > /dev/null 2>&1`
end
end
7 changes: 7 additions & 0 deletions spec/example.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Gem::Specification.new do |s|
s.name = 'example'
s.version = "1.2.3"
s.authors = ["Ruby Coder"]
s.files = ["lib/example.rb"]
s.summary = "This is an example!"
end
52 changes: 36 additions & 16 deletions spec/version_checker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,61 @@
require 'base64'

RSpec.describe VersionChecker do
let(:example_gemspec_path) { File.join(__dir__, "example.gemspec") }

it 'fetches version number of a gem from rubygems' do
stub_rubygems_call('6.0.1')

expect(subject.fetch_rubygems_version('govuk_app_config')).to eq('6.0.1')
expect(subject.fetch_rubygems_version('example')).to eq('6.0.1')
end

it 'fetches version number of a gem from GitHub' do
stub_github_call('9.7.0')
stub_github_call

expect(subject.fetch_gemspec('example').version).to eq('1.2.3')
end

it "fetches gemspecs for all govuk repos" do
stub_devdocs_call
stub_github_call

expect(subject.fetch_github_version('govuk_app_config')).to eq('9.7.0')
expect(subject.fetch_all_govuk_gemspecs).to eq([Gem::Specification.load(example_gemspec_path)])
end

it "compares versions of gems on GitHub and rubygems and it's a match" do
stub_github_call('9.7.0')
stub_rubygems_call('9.7.0')
it "detects when there are no version discrepancies" do
stub_devdocs_call
stub_github_call
stub_rubygems_call('1.2.3')

expect(subject.rubygems_and_github_match?('govuk_app_config')).to eq(true)
expect { subject.print_version_discrepancies }.to output("No discrepancies found!\n").to_stdout
end

it "compares versions of gems on GitHub and rubygems and it's not a match" do
stub_github_call('9.7.0')
stub_rubygems_call('9.7.1')
it "detects when there are are version discrepancies" do
stub_devdocs_call
stub_github_call
stub_rubygems_call('1.2.2')

expect(subject.rubygems_and_github_match?('govuk_app_config')).to eq(false)
expect { subject.print_version_discrepancies }.to output(
"Version mismatch for 'example':\n Version on RubyGems: 1.2.2\n Version on GitHub: 1.2.3\n"
).to_stdout
end

def stub_github_call(version)
repo = { content: Base64.encode64(%(module GovukAppConfig\n VERSION = "#{version}".freeze\nend\n)) }
stub_request(:get, 'https://api.github.com/repos/alphagov/govuk_app_config/contents/lib/govuk_app_config/version.rb')
.to_return(status: 200, body: repo.to_json, headers: { 'Content-Type' => 'application/json' })
def stub_github_call
allow(subject).to receive(:clone_github_repo) do
FileUtils.mkdir "example"
FileUtils.cp example_gemspec_path, File.join(Dir.pwd, "example")
end
end

def stub_rubygems_call(version)
repo = { "version": version }
stub_request(:get, 'https://rubygems.org/api/v1/gems/govuk_app_config.json')
stub_request(:get, 'https://rubygems.org/api/v1/gems/example.json')
.to_return(status: 200, body: repo.to_json, headers: {})
end

def stub_devdocs_call
repo = [{ "app_name": "example" }]
stub_request(:get, 'https://docs.publishing.service.gov.uk/gems.json')
.to_return(status: 200, body: repo.to_json, headers: {})
end
end

0 comments on commit 0b6e8be

Please sign in to comment.