Skip to content

Commit

Permalink
Add logic for parsing Gemfile.lock & comparating it to Rubygems
Browse files Browse the repository at this point in the history
  • Loading branch information
cilim committed Aug 6, 2024
1 parent 82b1d53 commit f45f294
Show file tree
Hide file tree
Showing 29 changed files with 516 additions and 9 deletions.
1 change: 1 addition & 0 deletions .browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
defaults
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
!/tmp/storage/.keep

/public/assets
/public/data

# Ignore master key for decrypting credentials and more.
/config/master.key
Expand All @@ -43,3 +44,8 @@ logfile
.DS_Store
config/application.yml
node_modules

/node_modules
/yarn-error.log
yarn-debug.log*
.yarn-integrity
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ gem 'bootsnap', require: false
gem 'bugsnag'
gem 'figaro'
gem 'importmap-rails'
gem 'progress_bar'
gem 'pg', '~> 1.1'
gem 'pry-byebug'
gem 'pry-rails'
gem 'puma', '>= 5.0'
gem 'rails_charts'
gem 'slim'
gem 'sprockets-rails'
gem 'stimulus-rails'
Expand Down
8 changes: 8 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ GEM
racc (~> 1.4)
nokogiri (1.16.7-x86_64-linux)
racc (~> 1.4)
options (2.3.2)
overcommit (0.64.0)
childprocess (>= 0.6.3, < 6)
iniparse (~> 1.4)
Expand All @@ -206,6 +207,9 @@ GEM
pastel (0.8.0)
tty-color (~> 0.5)
pg (1.5.7)
progress_bar (1.3.4)
highline (>= 1.6)
options (~> 2.3.0)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
Expand Down Expand Up @@ -248,6 +252,8 @@ GEM
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
rails_charts (0.0.6)
rails
railties (7.1.3.4)
actionpack (= 7.1.3.4)
activesupport (= 7.1.3.4)
Expand Down Expand Up @@ -395,10 +401,12 @@ DEPENDENCIES
mina-infinum
overcommit
pg (~> 1.1)
progress_bar
pry-byebug
pry-rails
puma (>= 5.0)
rails (~> 7.1.3, >= 7.1.3.2)
rails_charts
rspec-rails
rubocop-infinum
slim
Expand Down
1 change: 1 addition & 0 deletions app/assets/config/manifest.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
//= link_tree ../images
//= link_directory ../stylesheets .css
//= link application.js
14 changes: 14 additions & 0 deletions app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

require 'csv'

class ProjectsController < ApplicationController
def show
project_file_name = Chart::FileStorage.find(params[:id])

@project = Project.new(
project_file_name: project_file_name,
data: CSV.read(project_file_name, col_sep: ';').to_h
)
end
end
9 changes: 9 additions & 0 deletions app/domains/chart.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module Chart
def self.generate(**args)
generator = Chart::Generator.new(**args).create

Chart::FileStorage.create(name: generator.project_name, days: generator.days)
end
end
13 changes: 13 additions & 0 deletions app/domains/chart/day.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Chart
class Day
attr_reader :date
attr_reader :outdated_gem_count

def initialize(date:, outdated_gem_count:)
@date = date
@outdated_gem_count = outdated_gem_count
end
end
end
45 changes: 45 additions & 0 deletions app/domains/chart/file_storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

module Chart
class FileStorage
class << self
def create(**args)
new(**args).create
end

def find(name)
file = new(name: name)
raise ActiveRecord::RecordNotFound, 'file not found' unless File.exist?(file.file_path)

file.file_path
end
end

attr_reader :name

def initialize(name:, days: [])
@name = name
@days = days
@file = nil
end

def create
self.file = File.open(file_path, 'w') do |file|
days.each do |day|
file.puts "#{day.date};#{day.outdated_gem_count}"
end
end

self
end

def file_path
"#{Rails.root}/public/data/#{name}.csv"
end

private

attr_reader :days
attr_writer :file
end
end
70 changes: 70 additions & 0 deletions app/domains/chart/generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# frozen_string_literal: true

module Chart
class Generator
attr_reader :days

def initialize(start_date:, end_date:, repo:)
@start_date = start_date
@end_date = end_date
@repo = repo
@days = []
@progress = ProgressBar.new((end_date - start_date).to_i + 1)
end

def create
self.days = map_days

self
end

def project_name
repo.split('/').last
end

private

attr_reader :start_date
attr_reader :end_date
attr_reader :progress
attr_reader :repo
attr_writer :days

def map_days
previous_sha = nil

(start_date..end_date).map do |date|
sha = `cd #{repo} && git rev-list -1 --before="#{date}" master`.strip

`cd #{repo} && OVERCOMMIT_DISABLE=1 git checkout #{sha} Gemfile.lock > /dev/null 2>&1` if previous_sha != sha

count = outdated_gem_count(date)
previous_sha = sha
progress.increment!

Day.new(date:, outdated_gem_count: count)
end
end

def outdated_gem_count(time)
count = 0
parser.specs.each do |gem_specification|
gem = Rubygem.find_by(name: gem_specification.name)
current_version = gem.versions.release.find_by(number: gem_specification.version.to_s)
next if current_version.nil? || gem.versions.release.empty?

count += 1 if gem.versions.release.where(position: ...current_version.position, created_at: ...time).any?
end

count
end

def parser
Bundler::LockfileParser.new(gemfile_lock)
end

def gemfile_lock
Bundler.read_file("#{repo}/Gemfile.lock")
end
end
end
4 changes: 4 additions & 0 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails

import "echarts"
import "echarts/theme/dark"
11 changes: 11 additions & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class Project
include ActiveModel::Model

attr_accessor :project_file_name, :data

def name
project_file_name.split('/').last.split('.csv').first
end
end
16 changes: 16 additions & 0 deletions app/models/rubygem.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: rubygems
#
# id :integer not null, primary key
# name :string
# token :string
# created_at :datetime
# updated_at :datetime
# user_id :integer
#
class Rubygem < ApplicationRecord
has_many :versions, dependent: :destroy
end
25 changes: 25 additions & 0 deletions app/models/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: versions
#
# id :integer not null, primary key
# authors :string
# description :text
# downloads :integer default(0)
# number :string
# position :integer
# created_at :datetime
# updated_at :datetime
# rubygem_id :integer
#
# Indexes
#
# index_versions_on_position (position)
#
class Version < ApplicationRecord
belongs_to :rubygem

scope :release, -> { where(prerelease: false) }
end
1 change: 1 addition & 0 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>

<body>
Expand Down
2 changes: 2 additions & 0 deletions app/views/projects/show.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
h1 = @project.name
= bar_chart @project.data, class: 'box', theme: 'sakura', options: { series: { barWidth: '50%' } }
4 changes: 4 additions & 0 deletions bin/importmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby

require_relative "../config/application"
require "importmap/commands"
2 changes: 2 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Application < Rails::Application
# Don't generate system test files.
config.generators.system_tests = nil

routes.default_url_options[:host] = 'http://localhost:3000'

def secrets
config_for(:secrets)
end
Expand Down
5 changes: 5 additions & 0 deletions config/importmap.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Pin npm packages by running ./bin/importmap

pin "application", to: "application.js"
pin "echarts", to: "echarts.min.js"
pin "echarts/theme/dark", to: "echarts/theme/dark.js"
9 changes: 1 addition & 8 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
# Can be used by load balancers and uptime monitors to verify that the app is live.
get "up" => "rails/health#show", as: :rails_health_check

# Defines the root path route ("/")
# root "posts#index"
resources :projects, only: [:show]
end
14 changes: 14 additions & 0 deletions db/migrate/20090527122639_create_rubygems.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateRubygems < ActiveRecord::Migration[4.2]
def self.up
create_table :rubygems do |table|
table.string :name
table.string :token
table.integer :user_id
table.timestamps
end
end

def self.down
drop_table :rubygems
end
end
13 changes: 13 additions & 0 deletions db/migrate/20090527122649_create_versions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CreateVersions < ActiveRecord::Migration[4.2]
def change
create_table :versions do |table|
table.string :authors
table.text :description
table.integer :downloads, default: 0
table.string :number
table.integer :rubygem_id
table.integer :position, index: true
table.timestamps
end
end
end
23 changes: 22 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f45f294

Please sign in to comment.