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
13 changes: 8 additions & 5 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ gem 'hirb'
# gem 'hirb-unicode' # incompatible with new rubocop
gem 'sequel', '~> 5.0'

# Asynchronicity
gem 'aws-sdk-sqs', '~> 1.0'
gem 'concurrent-ruby', '~> 1.0'
gem 'shoryuken', '~> 6.0'

group :development, :test do
gem 'sqlite3', '~> 1.0'
end
Expand All @@ -60,6 +55,14 @@ group :production do
gem 'pg', '~> 1.0'
end

# Asynchronicity
gem 'aws-sdk-sqs', '~> 1.0'
gem 'concurrent-ruby', '~> 1.0'

# WORKER
gem 'faye', '~> 1.0'
gem 'shoryuken', '~> 6.0'

# TESTING
group :test do
# API Unit/Integration/Acceptance Tests
Expand Down
28 changes: 28 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ GEM
bigdecimal (3.3.1)
coderay (1.1.3)
concurrent-ruby (1.3.5)
cookiejar (0.3.4)
crack (1.0.1)
bigdecimal
rexml
Expand Down Expand Up @@ -83,6 +84,27 @@ GEM
dry-initializer (~> 3.2)
dry-schema (~> 1.14)
zeitwerk (~> 2.6)
em-http-request (1.1.7)
addressable (>= 2.3.4)
cookiejar (!= 0.3.1)
em-socksify (>= 0.3)
eventmachine (>= 1.0.3)
http_parser.rb (>= 0.6.0)
em-socksify (0.3.3)
base64
eventmachine (>= 1.0.0.beta.4)
eventmachine (1.2.7)
faye (1.4.1)
cookiejar (>= 0.3.0)
em-http-request (>= 1.1.6)
eventmachine (>= 0.12.0)
faye-websocket (>= 0.11.0)
multi_json (>= 1.0.0)
rack (>= 1.0.0)
websocket-driver (>= 0.5.1)
faye-websocket (0.12.0)
eventmachine (>= 0.12.0)
websocket-driver (>= 0.8.0)
ffi (1.17.2)
ffi (1.17.2-arm64-darwin)
ffi (1.17.2-x86_64-linux-gnu)
Expand All @@ -105,6 +127,7 @@ GEM
http-cookie (1.1.0)
domain_name (~> 0.5)
http-form_data (2.3.0)
http_parser.rb (0.8.0)
ice_nine (0.11.2)
jmespath (1.6.2)
json (2.17.1)
Expand Down Expand Up @@ -233,6 +256,10 @@ GEM
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
websocket-driver (0.8.0)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
zeitwerk (2.7.3)

PLATFORMS
Expand All @@ -249,6 +276,7 @@ DEPENDENCIES
dry-transaction (~> 0)
dry-types (~> 1.0)
dry-validation (~> 1.0)
faye (~> 1.0)
figaro (~> 1.0)
flog
hirb
Expand Down
1 change: 0 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ end

desc 'Run unit and integration tests'
Rake::TestTask.new(:spec) do |t|
puts 'Make sure worker is running in separate process'
t.pattern = 'spec/tests/**/*_spec.rb'
t.warning = false
end
Expand Down
8 changes: 7 additions & 1 deletion app/application/controllers/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,17 @@ class App < Roda
response.cache_control public: true, max_age: 300
end

request_id = [request.env, request.path, Time.now.to_f].hash

path_request = Request::ProjectPath.new(
owner_name, project_name, request
)

result = Service::AppraiseProject.new.call(requested: path_request)
result = Service::AppraiseProject.new.call(
requested: path_request,
request_id: request_id,
config: App.config
)

if result.failure?
failed = Representer::HttpResponse.new(result.failure)
Expand Down
21 changes: 15 additions & 6 deletions app/application/services/appraise_project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ class AppraiseProject
CLONE_ERR = 'Could not clone this project'
TOO_LARGE_ERR = 'Project is too large to analyze'
NO_FOLDER_ERR = 'Could not find that folder'
PROCESSING_MSG = 'Processing the appraisal request; please check back later'
PROCESSING_MSG = 'Processing the appraisal request'
# rubocop:enable Lint/UselessConstantScoping

# input hash keys expected: :project, :requested, :config
def find_project_details(input)
input[:project] = Repository::For.klass(Entity::Project).find_full_name(
input[:requested].owner_name, input[:requested].project_name
Expand All @@ -42,19 +43,21 @@ def check_project_eligibility(input)
if input[:project].too_large?
Failure(Response::ApiResult.new(status: :forbidden, message: TOO_LARGE_ERR))
else
input[:gitrepo] = GitRepo.new(input[:project])
input[:gitrepo] = GitRepo.new(input[:project], input[:config])
Success(input)
end
end

def request_cloning_worker(input)
return Success(input) if input[:gitrepo].exists_locally?

Messaging::Queue
.new(App.config.CLONE_QUEUE_URL, App.config)
.send(Representer::Project.new(input[:project]).to_json)
Messaging::Queue.new(App.config.CLONE_QUEUE_URL, App.config)
.send(clone_request_json(input))

Failure(Response::ApiResult.new(status: :processing, message: PROCESSING_MSG))
Failure(Response::ApiResult.new(
status: :processing,
message: { request_id: input[:request_id], msg: PROCESSING_MSG }
))
rescue StandardError => e
log_error(e)
Failure(Response::ApiResult.new(status: :internal_error, message: CLONE_ERR))
Expand Down Expand Up @@ -82,6 +85,12 @@ def full_request_path(input)
def log_error(error)
App.logger.error [error.inspect, error.backtrace].flatten.join("\n")
end

def clone_request_json(input)
Response::CloneRequest.new(input[:project], input[:request_id])
.then { Representer::CloneRequest.new(_1) }
.then(&:to_json)
end
end
end
end
6 changes: 3 additions & 3 deletions app/infrastructure/git/repositories/git_repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ class Errors
CannotOverwriteLocalGitRepo = Class.new(StandardError)
end

def initialize(project, config = CodePraise::App.config)
def initialize(project, config)
@project = project
remote = Git::RemoteGitRepo.new(@project.http_url)
@local = Git::LocalGitRepo.new(remote)
@local = Git::LocalGitRepo.new(remote, config.REPOSTORE_PATH)
end

def local
Expand All @@ -27,7 +27,7 @@ def exists_locally?
@local.exists?
end

def clone
def clone_locally
raise Errors::TooLargeToClone if @project.too_large?
raise Errors::CannotOverwriteLocalGitRepo if exists_locally?

Expand Down
4 changes: 2 additions & 2 deletions app/infrastructure/git/repositories/local_repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ class LocalGitRepo

attr_reader :git_repo_path

def initialize(remote)
def initialize(remote, repostore_path)
@remote = remote
@git_repo_path = [ENV['REPOSTORE_PATH'], @remote.unique_id].join('/')
@git_repo_path = [repostore_path, @remote.unique_id].join('/')
end

def clone_remote
Expand Down
18 changes: 18 additions & 0 deletions app/presentation/representers/clone_request_representer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require 'roar/decorator'
require 'roar/json'
require_relative 'project_representer'

# Represents essential Repo information for API output
module CodePraise
module Representer
# Representer object for project clone requests
class CloneRequest < Roar::Decorator
include Roar::JSON

property :project, extend: Representer::Project, class: OpenStruct
property :id
end
end
end
2 changes: 1 addition & 1 deletion app/presentation/representers/project_representer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Project < Roar::Decorator
collection :contributors, extend: Representer::Member, class: OpenStruct

link :self do
"#{App.config.API_HOST}/projects/#{project_name}/#{owner_name}"
"#{ENV.fetch('API_HOST')}/api/v1/projects/#{project_name}/#{owner_name}"
end

private
Expand Down
7 changes: 7 additions & 0 deletions app/presentation/responses/clone_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

module CodePraise
module Response
CloneRequest = Struct.new :project, :id
end
end
2 changes: 2 additions & 0 deletions config.ru
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

require 'faye'
require_relative 'require_app'
require_app

use Faye::RackAdapter, mount: '/faye', timeout: 25
run CodePraise::App.freeze.app
3 changes: 3 additions & 0 deletions config/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ def self.config = Figaro.env
end

configure :production do
puts 'RUNNING IN PRODUCTION MODE'
# Set DATABASE_URL environment variable on production platform

use Rack::Cache,
verbose: true,
metastore: "#{config.REDISCLOUD_URL}/0/metastore",
Expand Down
12 changes: 9 additions & 3 deletions config/secrets_example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ development:
AWS_ACCESS_KEY_ID: <aws credential>
AWS_SECRET_ACCESS_KEY: <aws credential>
AWS_REGION: <choose region>
CLONE_QUEUE: codepraise-clone-development
CLONE_QUEUE: soa-codepraise-clone-dev
CLONE_QUEUE_URL: <set by AWS>
REPORT_QUEUE: codepraise-report-development
REPORT_QUEUE_URL: <set by AWS

app_test:
DB_FILENAME: db/local/test.db
Expand All @@ -23,8 +25,10 @@ app_test:
AWS_ACCESS_KEY_ID: <aws credential>
AWS_SECRET_ACCESS_KEY: <aws credential>
AWS_REGION: <choose region>
CLONE_QUEUE: codepraise-clone-development
CLONE_QUEUE: codepraise-clone-test
CLONE_QUEUE_URL: <set by AWS>
REPORT_QUEUE: codepraise-report-test
REPORT_QUEUE_URL: <set by AWS

test:
DB_FILENAME: db/local/test.db
Expand All @@ -36,8 +40,10 @@ test:
AWS_ACCESS_KEY_ID: <aws credential>
AWS_SECRET_ACCESS_KEY: <aws credential>
AWS_REGION: <choose region>
CLONE_QUEUE: codepraise-clone-development
CLONE_QUEUE: codepraise-clone-test
CLONE_QUEUE_URL: <set by AWS>
REPORT_QUEUE: codepraise-report-test
REPORT_QUEUE_URL: <set by AWS

production:
# - assign DATABASE_URL in production
Expand Down
Loading