File: version.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (106 lines) | stat: -rw-r--r-- 3,760 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# frozen_string_literal: true

module Ci
  module Catalog
    module Resources
      # This class represents a CI/CD Catalog resource version.
      # Only versions which contain valid CI components are included in this table.
      class Version < ::ApplicationRecord
        include BulkInsertableAssociations
        include CacheMarkdownField
        include SemanticVersionable

        self.table_name = 'catalog_resource_versions'

        belongs_to :release, inverse_of: :catalog_resource_version
        belongs_to :catalog_resource, class_name: 'Ci::Catalog::Resource', inverse_of: :versions
        belongs_to :project, inverse_of: :catalog_resource_versions
        belongs_to :published_by, class_name: 'User'
        has_many :components, class_name: 'Ci::Catalog::Resources::Component', inverse_of: :version

        validates :release, presence: true, uniqueness: { message: N_('has already been published') }
        validates :catalog_resource, :project, presence: true
        validates :published_by, presence: true, on: :create
        validate :validate_published_by_is_release_author, on: :create

        scope :for_catalog_resources, ->(catalog_resources) { where(catalog_resource_id: catalog_resources) }
        scope :preloaded, -> { includes(:catalog_resource, project: [:route, { namespace: :route }], release: :author) }
        scope :by_name, ->(name) { joins(:release).merge(Release.where(tag: name)) }
        scope :by_sha, ->(sha) { joins(:release).merge(Release.where(sha: sha)) }
        scope :with_semver, -> { where.not(semver_major: nil) }
        scope :without_prerelease, -> { where(semver_prerelease: nil) }

        delegate :sha, :author_id, to: :release

        cache_markdown_field :readme

        before_create :sync_with_release
        after_destroy :update_catalog_resource
        after_save :update_catalog_resource

        class << self
          def latest(major = nil, minor = nil)
            raise ArgumentError, 'semver minor version used without major version' if minor.present? &&
              major.blank?

            relation = with_semver
            relation = relation.without_prerelease
            relation = relation.where(semver_major: major) if major
            relation = relation.where(semver_minor: minor) if minor

            relation.order_by_semantic_version_desc.first
          end

          def versions_for_catalog_resources(catalog_resources)
            return none if catalog_resources.empty?

            for_catalog_resources(catalog_resources).with_semver.order_by_semantic_version_desc
          end
        end

        def name
          semver.to_s
        end

        def commit
          project.commit_by(oid: sha)
        end

        def path
          Gitlab::Routing.url_helpers.project_tag_path(project, name)
        end

        def readme
          return unless project.repo_exists?

          project.repository.tree(sha).readme&.data
        end

        def sync_with_release!
          sync_with_release
          save!
        end

        private

        def sync_with_release
          self.released_at = release.released_at
        end

        def update_catalog_resource
          catalog_resource.update_latest_released_at!
        end

        # We require the published_by to be the same as the release author because
        # creating a release and publishing a version must be done in a single session via release-cli.
        def validate_published_by_is_release_author
          return if published_by == release.author

          errors.add(:published_by, 'must be the same as the release author')
        end
      end
    end
  end
end

Ci::Catalog::Resources::Version.prepend_mod_with('Ci::Catalog::Resources::Version')