Skip to content

Commit 7bbfeb0

Browse files
authored
Merge pull request #1683 from yez/main
Add Support for Storing Repo Labels
2 parents 31bd0e7 + 215fc26 commit 7bbfeb0

File tree

10 files changed

+230
-1
lines changed

10 files changed

+230
-1
lines changed

app/models/label.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Label < ActiveRecord::Base
2+
has_many :repo_labels
3+
has_many :repos, through: :repo_lables
4+
end

app/models/repo.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class Repo < ActiveRecord::Base
1616
has_many :doc_methods, dependent: :destroy
1717
delegate :open_issues, to: :issues
1818

19+
has_many :repo_labels
20+
has_many :labels, through: :repo_labels
21+
1922
before_validation :set_full_name!, :downcase_name, :strip_whitespaces
2023
after_create :background_populate_issues!, :update_repo_info!, :background_populate_docs!
2124

app/models/repo_label.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class RepoLabel < ActiveRecord::Base
2+
belongs_to :repo
3+
belongs_to :label
4+
end

app/services/repo_label_assigner.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
# PORO
4+
# This class takes in a repo and fetch all labels for that repo. It then
5+
# creates labels and associates them with the passed in repo
6+
#
7+
# Example:
8+
#
9+
# repo = Repo.first
10+
# assigner = RepoLabelAssigner.new(repo: repo)
11+
# assigner.create_and_associate_labels!
12+
#
13+
class RepoLabelAssigner
14+
def initialize(repo:)
15+
@repo = repo
16+
url = ['repos', repo.user_name, repo.name, 'labels'].join('/')
17+
@github_bub_response = GitHubBub.get(url)
18+
end
19+
20+
def create_and_associate_labels!
21+
return unless github_bub_response.success?
22+
23+
remote_labels.each do |label_hash|
24+
label_name = label_hash['name'].downcase
25+
label = Label.where(name: label_name).first_or_create!
26+
repo.repo_labels.where(label: label).first_or_create
27+
end
28+
end
29+
30+
private
31+
32+
attr_reader :github_bub_response, :repo
33+
34+
def remote_labels
35+
Array(github_bub_response.json_body)
36+
end
37+
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class CreateLabelsTable < ActiveRecord::Migration[6.1]
2+
def change
3+
create_table :labels do |t|
4+
t.string :name, null: false
5+
6+
t.timestamps
7+
end
8+
end
9+
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class CreateRepoLabelsTable < ActiveRecord::Migration[6.1]
2+
def change
3+
create_table :repo_labels do |t|
4+
t.references :repo, foreign_key: true, null: false
5+
t.references :label, foreign_key: true, null: false
6+
7+
t.timestamps
8+
end
9+
10+
add_index :repo_labels, [:repo_id, :label_id], unique: true
11+
end
12+
end

db/schema.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema.define(version: 2022_09_08_011235) do
13+
ActiveRecord::Schema.define(version: 2022_10_04_010749) do
1414

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

109+
create_table "labels", force: :cascade do |t|
110+
t.string "name", null: false
111+
t.datetime "created_at", precision: 6, null: false
112+
t.datetime "updated_at", precision: 6, null: false
113+
end
114+
115+
create_table "repo_labels", force: :cascade do |t|
116+
t.bigint "repo_id", null: false
117+
t.bigint "label_id", null: false
118+
t.datetime "created_at", precision: 6, null: false
119+
t.datetime "updated_at", precision: 6, null: false
120+
t.index ["label_id"], name: "index_repo_labels_on_label_id"
121+
t.index ["repo_id", "label_id"], name: "index_repo_labels_on_repo_id_and_label_id", unique: true
122+
t.index ["repo_id"], name: "index_repo_labels_on_repo_id"
123+
end
124+
109125
create_table "repo_subscriptions", id: :serial, force: :cascade do |t|
110126
t.datetime "created_at", null: false
111127
t.datetime "updated_at", null: false
@@ -190,6 +206,8 @@
190206
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
191207
end
192208

209+
add_foreign_key "repo_labels", "labels"
210+
add_foreign_key "repo_labels", "repos"
193211
add_foreign_key "repo_subscriptions", "repos"
194212
add_foreign_key "repo_subscriptions", "users"
195213
end

lib/tasks/schedule.rake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,11 @@ namespace :schedule do
111111
next unless Date.today.sunday?
112112
Rake::Task['sitemap:refresh'].invoke
113113
end
114+
115+
desc 'fetch and assign labels for repos'
116+
task fetch_labels_and_assign: :environment do
117+
Repo.find_each(batch_size: 100) do |repo|
118+
RepoLabelAssigner.new(repo: repo).create_and_associate_labels!
119+
end
120+
end
114121
end
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
5+
class RepoLabelsAssignerTest < ActiveSupport::TestCase
6+
test '#create_and_associate_labels! creates labels' do
7+
repo = repos(:rails_rails)
8+
VCR.use_cassette('fetch_labels_for_repo', record: :once) do
9+
assigner = RepoLabelAssigner.new(repo: repo)
10+
assert_difference('Label.count', 30) do
11+
assigner.create_and_associate_labels!
12+
end
13+
end
14+
end
15+
16+
test '#create_and_associate_labels! it does not create existing labels' do
17+
repo = repos(:rails_rails)
18+
Label.create!(name: :autoloading)
19+
VCR.use_cassette('fetch_labels_for_repo', record: :once) do
20+
assigner = RepoLabelAssigner.new(repo: repo)
21+
assigner.create_and_associate_labels!
22+
assert_equal Label.where(name: :autoloading).count, 1
23+
end
24+
end
25+
26+
test '#create_and_associate_labels! it does not care about label case' do
27+
repo = repos(:rails_rails)
28+
VCR.use_cassette('fetch_labels_for_repo', record: :once) do
29+
assigner = RepoLabelAssigner.new(repo: repo)
30+
assigner.create_and_associate_labels!
31+
assert_equal Label.where(name: :ActionMailer).count, 0
32+
end
33+
end
34+
35+
test '#create_and_associate_labels! associates labels with the repo' do
36+
repo = repos(:rails_rails)
37+
VCR.use_cassette('fetch_labels_for_repo', record: :once) do
38+
assigner = RepoLabelAssigner.new(repo: repo)
39+
assigner.create_and_associate_labels!
40+
end
41+
42+
assert_equal Label.count, RepoLabel.where(repo: repo).count
43+
end
44+
end

test/vcr_cassettes/fetch_labels_for_repo.yml

Lines changed: 91 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)