Skip to content

Commit

Permalink
Merge pull request #1683 from yez/main
Browse files Browse the repository at this point in the history
Add Support for Storing Repo Labels
  • Loading branch information
schneems authored Oct 5, 2022
2 parents 31bd0e7 + 215fc26 commit 7bbfeb0
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 1 deletion.
4 changes: 4 additions & 0 deletions app/models/label.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Label < ActiveRecord::Base
has_many :repo_labels
has_many :repos, through: :repo_lables
end
3 changes: 3 additions & 0 deletions app/models/repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class Repo < ActiveRecord::Base
has_many :doc_methods, dependent: :destroy
delegate :open_issues, to: :issues

has_many :repo_labels
has_many :labels, through: :repo_labels

before_validation :set_full_name!, :downcase_name, :strip_whitespaces
after_create :background_populate_issues!, :update_repo_info!, :background_populate_docs!

Expand Down
4 changes: 4 additions & 0 deletions app/models/repo_label.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class RepoLabel < ActiveRecord::Base
belongs_to :repo
belongs_to :label
end
37 changes: 37 additions & 0 deletions app/services/repo_label_assigner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

# PORO
# This class takes in a repo and fetch all labels for that repo. It then
# creates labels and associates them with the passed in repo
#
# Example:
#
# repo = Repo.first
# assigner = RepoLabelAssigner.new(repo: repo)
# assigner.create_and_associate_labels!
#
class RepoLabelAssigner
def initialize(repo:)
@repo = repo
url = ['repos', repo.user_name, repo.name, 'labels'].join('/')
@github_bub_response = GitHubBub.get(url)
end

def create_and_associate_labels!
return unless github_bub_response.success?

remote_labels.each do |label_hash|
label_name = label_hash['name'].downcase
label = Label.where(name: label_name).first_or_create!
repo.repo_labels.where(label: label).first_or_create
end
end

private

attr_reader :github_bub_response, :repo

def remote_labels
Array(github_bub_response.json_body)
end
end
9 changes: 9 additions & 0 deletions db/migrate/20221004010742_create_labels_table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class CreateLabelsTable < ActiveRecord::Migration[6.1]
def change
create_table :labels do |t|
t.string :name, null: false

t.timestamps
end
end
end
12 changes: 12 additions & 0 deletions db/migrate/20221004010749_create_repo_labels_table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateRepoLabelsTable < ActiveRecord::Migration[6.1]
def change
create_table :repo_labels do |t|
t.references :repo, foreign_key: true, null: false
t.references :label, foreign_key: true, null: false

t.timestamps
end

add_index :repo_labels, [:repo_id, :label_id], unique: true
end
end
20 changes: 19 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.define(version: 2022_09_08_011235) do
ActiveRecord::Schema.define(version: 2022_10_04_010749) do

# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
Expand Down Expand Up @@ -106,6 +106,22 @@
t.index ["updated_at"], name: "index_issues_on_updated_at", where: "((state)::text = 'open'::text)"
end

create_table "labels", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end

create_table "repo_labels", force: :cascade do |t|
t.bigint "repo_id", null: false
t.bigint "label_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["label_id"], name: "index_repo_labels_on_label_id"
t.index ["repo_id", "label_id"], name: "index_repo_labels_on_repo_id_and_label_id", unique: true
t.index ["repo_id"], name: "index_repo_labels_on_repo_id"
end

create_table "repo_subscriptions", id: :serial, force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
Expand Down Expand Up @@ -190,6 +206,8 @@
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end

add_foreign_key "repo_labels", "labels"
add_foreign_key "repo_labels", "repos"
add_foreign_key "repo_subscriptions", "repos"
add_foreign_key "repo_subscriptions", "users"
end
7 changes: 7 additions & 0 deletions lib/tasks/schedule.rake
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,11 @@ namespace :schedule do
next unless Date.today.sunday?
Rake::Task['sitemap:refresh'].invoke
end

desc 'fetch and assign labels for repos'
task fetch_labels_and_assign: :environment do
Repo.find_each(batch_size: 100) do |repo|
RepoLabelAssigner.new(repo: repo).create_and_associate_labels!
end
end
end
44 changes: 44 additions & 0 deletions test/unit/repo_labels_assigner_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

require 'test_helper'

class RepoLabelsAssignerTest < ActiveSupport::TestCase
test '#create_and_associate_labels! creates labels' do
repo = repos(:rails_rails)
VCR.use_cassette('fetch_labels_for_repo', record: :once) do
assigner = RepoLabelAssigner.new(repo: repo)
assert_difference('Label.count', 30) do
assigner.create_and_associate_labels!
end
end
end

test '#create_and_associate_labels! it does not create existing labels' do
repo = repos(:rails_rails)
Label.create!(name: :autoloading)
VCR.use_cassette('fetch_labels_for_repo', record: :once) do
assigner = RepoLabelAssigner.new(repo: repo)
assigner.create_and_associate_labels!
assert_equal Label.where(name: :autoloading).count, 1
end
end

test '#create_and_associate_labels! it does not care about label case' do
repo = repos(:rails_rails)
VCR.use_cassette('fetch_labels_for_repo', record: :once) do
assigner = RepoLabelAssigner.new(repo: repo)
assigner.create_and_associate_labels!
assert_equal Label.where(name: :ActionMailer).count, 0
end
end

test '#create_and_associate_labels! associates labels with the repo' do
repo = repos(:rails_rails)
VCR.use_cassette('fetch_labels_for_repo', record: :once) do
assigner = RepoLabelAssigner.new(repo: repo)
assigner.create_and_associate_labels!
end

assert_equal Label.count, RepoLabel.where(repo: repo).count
end
end
91 changes: 91 additions & 0 deletions test/vcr_cassettes/fetch_labels_for_repo.yml

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

0 comments on commit 7bbfeb0

Please sign in to comment.