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
schneems authored Oct 5, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 31bd0e7 + 215fc26 commit 7bbfeb0
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
@@ -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!

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
@@ -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"
@@ -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
@@ -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
@@ -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.