Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ gem "kredis", "~> 1.2"
gem "net-pop", github: "ruby/net-pop"
gem "octokit", "~> 9.1"
gem "octopoller", "~> 0.3"
gem "ostruct"
gem "propshaft", "~> 0.8"
gem "pry-rails", "~> 0.3"
gem "puma", "~> 6.4"
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ GEM
faraday (>= 1, < 3)
sawyer (~> 0.9)
octopoller (0.3.1)
ostruct (0.6.3)
pg (1.5.6)
popper_js (2.11.8)
pp (0.6.3)
Expand Down Expand Up @@ -471,6 +472,7 @@ GEM
PLATFORMS
arm64-darwin-23
arm64-darwin-24
arm64-darwin-25
x86_64-linux

DEPENDENCIES
Expand Down Expand Up @@ -501,6 +503,7 @@ DEPENDENCIES
net-pop!
octokit (~> 9.1)
octopoller (~> 0.3)
ostruct
pg
propshaft (~> 0.8)
pry-rails (~> 0.3)
Expand Down
39 changes: 38 additions & 1 deletion app/controllers/gemmies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,19 @@ def index
end

def show
@gemmy = Gemmy.find_by_name!(params[:id])
@gemmy = Gemmy.find_by_name(params[:id])

if @gemmy
respond_to do |format|
format.html
format.json { render json: gemmy_compatibility_json(@gemmy) }
end
else
respond_to do |format|
format.html { head :not_found }
format.json { render json: { error: "Gem not found" }, status: :not_found }
end
end
end

def compat_table
Expand All @@ -37,6 +49,31 @@ def compat_table

private

def gemmy_compatibility_json(gemmy)
rails_releases = RailsRelease.all.sort_by { |release| Gem::Version.new(release.version.to_s) }

{
name: gemmy.name,
compatibility: rails_releases.map { |rails_release|
compats = gemmy.compats_for_rails_release(rails_release)
status = helpers.compats_status(gemmy, compats)

{
rails_version: rails_release.version.to_s,
status: status.to_s,
compats: compats.map { |compat|
{
id: compat.id,
status: compat.status,
dependencies: compat.dependencies,
checked_at: compat.checked_at
}
}
}
}
}
end

def gemmy_params
params.require(:gemmy).permit(:name)
end
Expand Down
2 changes: 1 addition & 1 deletion spec/controllers/email_notifications_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
it "renders the form partial with unprocessable entity status" do
post :create, params: invalid_params
expect(response).to render_template(partial: "email_notifications/_form")
expect(response).to have_http_status(:unprocessable_entity)
expect(response).to have_http_status(:unprocessable_content)
end
end

Expand Down
97 changes: 97 additions & 0 deletions spec/requests/api/compats_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
require "rails_helper"

RSpec.describe "Gemmies JSON API", type: :request do
include FactoryBot::Syntax::Methods

describe "GET /gems/:id.json" do
context "when the gem exists with compats" do
let(:rails_71) { create(:rails_release, version: "7.1") }
let(:rails_72) { create(:rails_release, version: "7.2") }
let(:gemmy) { create(:gemmy, name: "devise") }
let!(:compatible_compat) do
create(:compat,
rails_release: rails_71,
dependencies: { "devise" => "~> 4.9" },
status: :compatible,
checked_at: Time.current,
status_determined_by: "bundler"
)
end
let!(:incompatible_compat) do
create(:compat,
rails_release: rails_72,
dependencies: { "devise" => "~> 3.0" },
status: :incompatible,
checked_at: Time.current,
status_determined_by: "bundler"
)
end

before do
gemmy.update!(compat_ids: [compatible_compat.id, incompatible_compat.id])
end

it "returns gem name and compatibility per Rails version" do
get "/gems/devise.json"

expect(response).to have_http_status(:ok)
expect(response.content_type).to include("application/json")

json = JSON.parse(response.body)
expect(json["name"]).to eq("devise")
expect(json["compatibility"]).to be_an(Array)
expect(json["compatibility"].size).to eq(2)

compat_71 = json["compatibility"].find { |c| c["rails_version"] == "7.1" }
expect(compat_71["status"]).to eq("compatible")
expect(compat_71["compats"]).to be_an(Array)
expect(compat_71["compats"].first["dependencies"]).to eq({ "devise" => "~> 4.9" })

compat_72 = json["compatibility"].find { |c| c["rails_version"] == "7.2" }
expect(compat_72["status"]).to eq("incompatible")
end
end

context "when the gem has pending compats" do
let(:rails_release) { create(:rails_release, version: "7.1") }
let(:gemmy) { create(:gemmy, name: "sidekiq") }
let!(:pending_compat) do
create(:compat,
rails_release: rails_release,
dependencies: { "sidekiq" => "~> 7.0" },
status: :pending
)
end

before do
gemmy.update!(compat_ids: [pending_compat.id])
end

it "returns checking status" do
get "/gems/sidekiq.json"

expect(response).to have_http_status(:ok)

json = JSON.parse(response.body)
compat = json["compatibility"].first
expect(compat["status"]).to eq("checking")
end
end

context "when the gem has no compats for a Rails version" do
let!(:rails_release) { create(:rails_release, version: "7.1") }
let!(:gemmy) { create(:gemmy, name: "tiny_gem", compat_ids: []) }

it "returns checking status for that version" do
get "/gems/tiny_gem.json"

expect(response).to have_http_status(:ok)

json = JSON.parse(response.body)
compat = json["compatibility"].first
expect(compat["rails_version"]).to eq("7.1")
expect(compat["status"]).to eq("checking")
end
end
end
end