From 8a3992e8c3cdef7d956dd5e95f53e9125b9912a6 Mon Sep 17 00:00:00 2001
From: moaz-khalifa <mkhalifa@gitlab.com>
Date: Thu, 16 May 2024 15:33:04 +0300
Subject: [PATCH] Create RPM package class

---
 app/models/packages/package.rb             |  4 ++--
 app/models/packages/rpm/metadatum.rb       | 12 +-----------
 app/models/packages/rpm/package.rb         | 13 +++++++++++++
 db/docs/packages_packages.yml              |  1 +
 locale/gitlab.pot                          |  3 ---
 spec/factories/packages/packages.rb        |  6 ------
 spec/factories/packages/rpm/packages.rb    |  9 +++++++++
 spec/models/packages/package_spec.rb       |  1 -
 spec/models/packages/rpm/metadatum_spec.rb | 14 ++------------
 spec/models/packages/rpm/package_spec.rb   |  9 +++++++++
 10 files changed, 37 insertions(+), 35 deletions(-)
 create mode 100644 app/models/packages/rpm/package.rb
 create mode 100644 spec/factories/packages/rpm/packages.rb
 create mode 100644 spec/models/packages/rpm/package_spec.rb

diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 52ec88a3f22de..f6f352c685a1c 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -50,7 +50,6 @@ class Packages::Package < ApplicationRecord
   has_one :nuget_metadatum, inverse_of: :package, class_name: 'Packages::Nuget::Metadatum'
   has_many :nuget_symbols, inverse_of: :package, class_name: 'Packages::Nuget::Symbol'
   has_one :composer_metadatum, inverse_of: :package, class_name: 'Packages::Composer::Metadatum'
-  has_one :rpm_metadatum, inverse_of: :package, class_name: 'Packages::Rpm::Metadatum'
   has_one :npm_metadatum, inverse_of: :package, class_name: 'Packages::Npm::Metadatum'
   has_one :terraform_module_metadatum, inverse_of: :package, class_name: 'Packages::TerraformModule::Metadatum'
   has_many :build_infos, inverse_of: :package
@@ -219,7 +218,8 @@ def self.inheritance_column_to_class_map = {
     ml_model: 'Packages::MlModel::Package',
     golang: 'Packages::Go::Package',
     rubygems: 'Packages::Rubygems::Package',
-    conan: 'Packages::Conan::Package'
+    conan: 'Packages::Conan::Package',
+    rpm: 'Packages::Rpm::Package'
   }.freeze
 
   def self.only_maven_packages_with_path(path, use_cte: false)
diff --git a/app/models/packages/rpm/metadatum.rb b/app/models/packages/rpm/metadatum.rb
index 7ee9e2d006456..eb6e41606e594 100644
--- a/app/models/packages/rpm/metadatum.rb
+++ b/app/models/packages/rpm/metadatum.rb
@@ -5,7 +5,7 @@ module Rpm
     class Metadatum < ApplicationRecord
       self.primary_key = :package_id
 
-      belongs_to :package, -> { where(package_type: :rpm) }, inverse_of: :rpm_metadatum
+      belongs_to :package, class_name: 'Packages::Rpm::Package', inverse_of: :rpm_metadatum
 
       validates :package, presence: true
       validates :epoch, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
@@ -15,16 +15,6 @@ class Metadatum < ApplicationRecord
       validates :arch, presence: true, length: { maximum: 255 }
       validates :license, allow_nil: true, length: { maximum: 1000 }
       validates :url, allow_nil: true, length: { maximum: 1000 }
-
-      validate :rpm_package_type
-
-      private
-
-      def rpm_package_type
-        return if package&.rpm?
-
-        errors.add(:base, _('Package type must be RPM'))
-      end
     end
   end
 end
diff --git a/app/models/packages/rpm/package.rb b/app/models/packages/rpm/package.rb
new file mode 100644
index 0000000000000..fe1ef0893c95f
--- /dev/null
+++ b/app/models/packages/rpm/package.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Packages
+  module Rpm
+    class Package < ::Packages::Package
+      self.allow_legacy_sti_class = true
+
+      INSTALLABLE_STATUSES = %i[default hidden].freeze
+
+      has_one :rpm_metadatum, inverse_of: :package, class_name: 'Packages::Rpm::Metadatum'
+    end
+  end
+end
diff --git a/db/docs/packages_packages.yml b/db/docs/packages_packages.yml
index 129151b72eca4..14d2e5cfceebf 100644
--- a/db/docs/packages_packages.yml
+++ b/db/docs/packages_packages.yml
@@ -5,6 +5,7 @@ classes:
 - Packages::Go::Package
 - Packages::MlModel::Package
 - Packages::Package
+- Packages::Rpm::Package
 - Packages::Rubygems::Package
 feature_categories:
 - package_registry
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 37a3a4a8bacf5..5a3d60d547e5d 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -36417,9 +36417,6 @@ msgstr ""
 msgid "Package type must be PyPi"
 msgstr ""
 
-msgid "Package type must be RPM"
-msgstr ""
-
 msgid "Package type must be Terraform Module"
 msgstr ""
 
diff --git a/spec/factories/packages/packages.rb b/spec/factories/packages/packages.rb
index a991a8b7a1bd4..46325426c941b 100644
--- a/spec/factories/packages/packages.rb
+++ b/spec/factories/packages/packages.rb
@@ -43,12 +43,6 @@
       end
     end
 
-    factory :rpm_package do
-      sequence(:name) { |n| "package-#{n}" }
-      sequence(:version) { |n| "v1.0.#{n}" }
-      package_type { :rpm }
-    end
-
     factory :debian_package do
       sequence(:name) { |n| "#{FFaker::Lorem.word}#{n}" }
       sequence(:version) { |n| "1.0-#{n}" }
diff --git a/spec/factories/packages/rpm/packages.rb b/spec/factories/packages/rpm/packages.rb
new file mode 100644
index 0000000000000..2b19303d5cf38
--- /dev/null
+++ b/spec/factories/packages/rpm/packages.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+  factory :rpm_package, class: 'Packages::Rpm::Package', parent: :package do
+    sequence(:name) { |n| "package-#{n}" }
+    sequence(:version) { |n| "v1.0.#{n}" }
+    package_type { :rpm }
+  end
+end
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 86337e3de2bf7..6feb4ff9a6e9d 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -22,7 +22,6 @@
     it { is_expected.to have_one(:debian_distribution).through(:debian_publication).source(:distribution).inverse_of(:packages).class_name('Packages::Debian::ProjectDistribution') }
     it { is_expected.to have_one(:nuget_metadatum).inverse_of(:package) }
     it { is_expected.to have_one(:npm_metadatum).inverse_of(:package) }
-    it { is_expected.to have_one(:rpm_metadatum).inverse_of(:package) }
     it { is_expected.to have_one(:terraform_module_metadatum).inverse_of(:package) }
     it { is_expected.to have_many(:nuget_symbols).inverse_of(:package) }
     it { is_expected.to have_many(:matching_package_protection_rules).through(:project).source(:package_protection_rules) }
diff --git a/spec/models/packages/rpm/metadatum_spec.rb b/spec/models/packages/rpm/metadatum_spec.rb
index 0e7817fdf8636..54809d27ce81b 100644
--- a/spec/models/packages/rpm/metadatum_spec.rb
+++ b/spec/models/packages/rpm/metadatum_spec.rb
@@ -1,9 +1,9 @@
 # frozen_string_literal: true
 require 'spec_helper'
 
-RSpec.describe Packages::Rpm::Metadatum, type: :model do
+RSpec.describe Packages::Rpm::Metadatum, type: :model, feature_category: :package_registry do
   describe 'relationships' do
-    it { is_expected.to belong_to(:package) }
+    it { is_expected.to belong_to(:package).class_name('Packages::Rpm::Package') }
   end
 
   describe 'validations' do
@@ -22,15 +22,5 @@
     it { is_expected.to validate_length_of(:arch).is_at_most(255) }
     it { is_expected.to validate_length_of(:license).is_at_most(1000) }
     it { is_expected.to validate_length_of(:url).is_at_most(1000) }
-
-    describe '#rpm_package_type' do
-      it 'will not allow a package with a different package_type' do
-        package = build('conan_package')
-        rpm_metadatum = build('rpm_metadatum', package: package)
-
-        expect(rpm_metadatum).not_to be_valid
-        expect(rpm_metadatum.errors.to_a).to include('Package type must be RPM')
-      end
-    end
   end
 end
diff --git a/spec/models/packages/rpm/package_spec.rb b/spec/models/packages/rpm/package_spec.rb
new file mode 100644
index 0000000000000..24dcd712ff185
--- /dev/null
+++ b/spec/models/packages/rpm/package_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Rpm::Package, type: :model, feature_category: :package_registry do
+  describe 'associations' do
+    it { is_expected.to have_one(:rpm_metadatum).inverse_of(:package).class_name('Packages::Rpm::Metadatum') }
+  end
+end
-- 
GitLab