Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for projects #63

Merged
merged 9 commits into from
Nov 9, 2021
4 changes: 4 additions & 0 deletions app/controllers/madmin/projects_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Madmin
class ProjectsController < Madmin::ResourceController
end
end
45 changes: 36 additions & 9 deletions app/controllers/reports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@ class ReportsController < ApplicationController

def create
data = request.body.read
begin
input = JSON.parse data
rescue => err
logger.fatal("Error: #{err.message} || #{data}")
head 400
return
end
input = JSON.parse data

entries = input["entries"]
project = find_project(input)

unless entries.is_a? Array
head 400
Expand All @@ -38,7 +33,7 @@ def create
end
end

rep = Report.create report: JSON.generate(entries)
rep = create_report(project, entries)

options = input["options"] || {}

Expand All @@ -48,10 +43,42 @@ def create

rep.save

render json: {id: rep.slug}
render json: response_hash(rep)
rescue => err
logger.fatal("Error: #{err.message} || #{data}")
head 400
nil
end

def show
@report = Report.find_by slug: params[:id]
end

private

def create_report(project, entries)
if project
project.reports.create report: JSON.generate(entries)
else
Report.create report: JSON.generate(entries)
end
end

def find_project(input)
return if input["project"].blank?

if input["project"]["id"]
Project.find(input["project"]["id"])
elsif input["project"]["permalink"]
Project.find_or_create_by(permalink: input["project"]["permalink"])
lubc marked this conversation as resolved.
Show resolved Hide resolved
end
end

def response_hash(report)
if report.project.present?
{id: report.slug, project_id: report.project_id}
else
{id: report.slug}
end
end
end
5 changes: 5 additions & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Project < ActiveRecord::Base
has_many :reports

validates :permalink, uniqueness: true
end
1 change: 1 addition & 0 deletions app/models/report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class Report < ActiveRecord::Base
validates :slug, uniqueness: true
validate :validate_parseability

belongs_to :project, optional: true
has_many :analyzed_files

def build_files
Expand Down
19 changes: 19 additions & 0 deletions db/migrate/20211106175125_add_projects.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class AddProjects < ActiveRecord::Migration[6.1]
def up
create_table :projects do |t|
t.string :git_url
t.string :permalink
t.string :name
t.timestamps
end

add_reference :reports, :project, foreign_key: true
add_index :projects, :permalink, unique: true
end

def down
remove_reference :reports, :project, foreign_key: true

drop_table :projects
end
end
18 changes: 15 additions & 3 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `rails
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2021_03_27_014813) do
ActiveRecord::Schema.define(version: 2021_11_06_175125) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand All @@ -28,12 +28,24 @@
t.index ["report_id"], name: "index_analyzed_files_on_report_id"
end

create_table "projects", force: :cascade do |t|
t.string "git_url"
t.string "permalink"
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["permalink"], name: "index_projects_on_permalink", unique: true
end

create_table "reports", id: :serial, force: :cascade do |t|
t.text "report"
t.boolean "compare"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.bigint "project_id"
t.index ["project_id"], name: "index_reports_on_project_id"
end

add_foreign_key "reports", "projects"
end
127 changes: 127 additions & 0 deletions test/controllers/reports_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,96 @@ class ReportsControllerTest < ActionController::TestCase
assert_equal JSON.parse(raw), report.data
end

test "creates a project with a new permalink and attaches the report to it" do
permalink = "github/fastruby/skunk"
data = <<~DATA
{
"project": {
"permalink": "#{permalink}"
},
"entries":
[{
"file": "lib/skunk/share.rb",
"skunk_score": "127.64",
"churn_times_cost": "2.55",
"churn": "2",
"cost": "1.28",
"coverage": "0.0"
}],
"summary": {
"total_skunk_score": "278.58",
"analysed_modules_count": "17",
"skunk_score_average": "16.39",
"skunk_version": "0.4.2",
"worst_skunk_score": {
"file": "lib/skunk/share.rb",
"skunk_score": "127.64"
}
},
"options": {
"compare": "false"
}
}
DATA

post :create, body: data

assert_equal "200", @response.code

rep = JSON.parse @response.body

report = Report.find_by slug: rep["id"]
project = report.project

assert_equal project.permalink, permalink
end

test "assigns a project to an existing project" do
etagwerker marked this conversation as resolved.
Show resolved Hide resolved
permalink = "github/fastruby/skunk"
existing_project = Project.create(permalink: permalink)
project_id = existing_project.id
data = <<~DATA
{
"project": {
"id": "#{project_id}"
},
"entries":
[{
"file": "lib/skunk/share.rb",
"skunk_score": "127.64",
"churn_times_cost": "2.55",
"churn": "2",
"cost": "1.28",
"coverage": "0.0"
}],
"summary": {
"total_skunk_score": "278.58",
"analysed_modules_count": "17",
"skunk_score_average": "16.39",
"skunk_version": "0.4.2",
"worst_skunk_score": {
"file": "lib/skunk/share.rb",
"skunk_score": "127.64"
}
},
"options": {
"compare": "false"
}
}
DATA

post :create, body: data

assert_equal "200", @response.code

rep = JSON.parse @response.body

report = Report.find_by slug: rep["id"]
project = report.project

assert_equal project, existing_project
end

test "errors on unknown data keys" do
data = <<-DATA
{
Expand Down Expand Up @@ -93,6 +183,43 @@ class ReportsControllerTest < ActionController::TestCase
assert_equal "400", @response.code
end

test "errors on unknown project" do
project_id = "-1"
data = <<~DATA
{
"project": {
"id": "#{project_id}"
},
"entries":
[{
"file": "lib/skunk/share.rb",
"skunk_score": "127.64",
"churn_times_cost": "2.55",
"churn": "2",
"cost": "1.28",
"coverage": "0.0"
}],
"summary": {
"total_skunk_score": "278.58",
"analysed_modules_count": "17",
"skunk_score_average": "16.39",
"skunk_version": "0.4.2",
"worst_skunk_score": {
"file": "lib/skunk/share.rb",
"skunk_score": "127.64"
}
},
"options": {
"compare": "false"
}
}
DATA

post :create, body: data

assert_equal "400", @response.code
end

test "errors out if there are keys missing" do
data = <<-DATA
{
Expand Down