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

Adds routine to keep repo up to date #1722

Merged
merged 7 commits into from
Oct 19, 2022
4 changes: 4 additions & 0 deletions app/models/github_fetcher/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ def success?
false
end

def not_found?
status == 404 ? true : false
end

def bad_token?
if status == 401 && response.body.match?(/Bad credentials/)
@error = @error_message = "Bad credentials"
Expand Down
29 changes: 22 additions & 7 deletions app/models/repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def fetcher
end

def fetcher_json
fetcher.as_json
@fetcher_json ||= fetcher.as_json
end

def issues_fetcher
Expand Down Expand Up @@ -192,12 +192,27 @@ def self.exists_with_name?(name)
end

def update_from_github
json = fetcher.as_json
self.update(
language: json.fetch('language', language),
description: json.fetch('description', description)&.first(255),
stars_count: json.fetch('stargazers_count', stars_count)
)
if fetcher.not_found?
self.update!(removed_from_github: true)
elsif fetcher.success?
repo_full_name = fetcher_json.fetch('full_name', full_name)

if repo_full_name != full_name && self.class.exists_with_name?(repo_full_name)
# TODO: Add deduplication step
return
end

repo_user_name, repo_name = repo_full_name.split("/")
self.update!(
name: repo_name,
user_name: repo_user_name,
language: fetcher_json.fetch('language', language),
description: fetcher_json.fetch('description', description)&.first(255),
full_name: repo_full_name,
removed_from_github: false,
archived: fetcher_json.fetch('archived', archived)
)
end
end

def repo_path
Expand Down
6 changes: 6 additions & 0 deletions db/migrate/20221013212959_add_archived_column_to_repo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddArchivedColumnToRepo < ActiveRecord::Migration[7.0]
def change
add_column :repos, :archived, :boolean, default: false
add_index :repos, :archived
end
end
4 changes: 3 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2022_10_10_011048) do
ActiveRecord::Schema[7.0].define(version: 2022_10_13_212959) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "plpgsql"
Expand Down Expand Up @@ -155,6 +155,8 @@
t.integer "subscribers_count", default: 0
t.integer "docs_subscriber_count", default: 0
t.boolean "removed_from_github", default: false
t.boolean "archived", default: false
t.index ["archived"], name: "index_repos_on_archived"
t.index ["full_name"], name: "index_repos_on_full_name"
t.index ["issues_count"], name: "index_repos_on_issues_count"
t.index ["language"], name: "index_repos_on_language"
Expand Down
13 changes: 4 additions & 9 deletions lib/tasks/schedule.rake
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,12 @@ namespace :schedule do
return GithubFetcher::Repo.new(user_name: "rails", name: "rails").success?
end

desc "Checks if repos have been deleted on GitHub"
task mark_removed_repos: :environment do
desc "Update repos information"
task update_repos: :environment do
raise "GITHUB API APPEARS TO BE DOWN" unless github_api_up?

Repo.select(:id, :user_name, :name).find_each(batch_size: 100) do |repo|
fetcher = GithubFetcher::Repo.new(user_name: repo.user_name, name: repo.name)
fetcher.call(retry_on_bad_token: 5)

if fetcher.response.status == 404
repo.update!(removed_from_github: true)
end
Repo.find_each(batch_size: 100) do |repo|
repo.update_repo_info!
end
end

Expand Down
73 changes: 69 additions & 4 deletions test/jobs/update_repo_info_job_test.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,74 @@
# frozen_string_literal: true

require 'test_helper'

class UpdateRepoInfoJobTest < ActiveJob::TestCase
# test "the truth" do
# assert true
# end
test 'repo deleted or made private' do
GithubFetcher::Resource.any_instance.stubs(:status).returns(404)
repo = repos(:node)
assert_changes -> {
[
repo.removed_from_github,
]
} do
UpdateRepoInfoJob.perform_now(repo)
repo.reload
end
assert repo.removed_from_github
end

test 'repo with information updated' do
GithubFetcher::Resource.any_instance.stubs(:status).returns(200)
GithubFetcher::Resource.any_instance.stubs(:as_json).returns(
{
'full_name' => 'test_owner/test_repo',
'language' => 'test_language',
'description' => 'test_description',
'archived' => true
}
)
repo = repos(:node)
assert_changes -> {
[
repo.full_name,
repo.name,
repo.user_name,
repo.language,
repo.description,
repo.archived
]
} do
UpdateRepoInfoJob.perform_now(repo)
repo.reload
end
assert_equal false, repo.removed_from_github
assert_equal 'test_owner/test_repo', repo.full_name
assert_equal 'test_repo', repo.name
assert_equal 'test_owner', repo.user_name
assert_equal 'test_language', repo.language
assert_equal 'test_description', repo.description
assert_equal true, repo.archived
end

test 'repo rename conflict' do
GithubFetcher::Resource.any_instance.stubs(:status).returns(200)
GithubFetcher::Resource.any_instance.stubs(:as_json).returns(
{
'full_name' => 'sinatra/sinatra',
}
)
repo = repos(:node)
assert_no_changes -> {
[
repo.full_name,
repo.name,
repo.user_name,
repo.language,
repo.description,
repo.archived
]
} do
UpdateRepoInfoJob.perform_now(repo)
repo.reload
end
end
end
19 changes: 19 additions & 0 deletions test/unit/github_fetcher/resource_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

require 'test_helper'

class GithubFetcher::ResourceTest < ActiveSupport::TestCase
def status_validation(mocked_status, method, expected_response)
GithubFetcher::Resource.any_instance.stubs(:status).returns(mocked_status)
resource = GithubFetcher::Resource.new({})
assert_equal expected_response, resource.send(method)
end

test '#not_found? is true on 404 status responses' do
status_validation(404, :not_found?, true)
end

test '#not_found? is false on non 404 status responses' do
[200, 201, 204, 400, 403, 500, 502].each { |status| status_validation(status, :not_found?, false) }
end
end