Class: Packages::Package

Inherits:
ApplicationRecord show all
Includes:
EachBatch, EnumInheritance, Gitlab::SQL::Pattern, Gitlab::Utils::StrongMemoize, Downloadable, Installable, Sortable, UsageStatistics
Defined in:
app/models/packages/package.rb

Direct Known Subclasses

MlModel::Package

Constant Summary collapse

DISPLAYABLE_STATUSES =
[:default, :error].freeze
INSTALLABLE_STATUSES =
[:default, :hidden].freeze
STATUS_MESSAGE_MAX_LENGTH =
255

Constants included from Gitlab::SQL::Pattern

Gitlab::SQL::Pattern::MIN_CHARS_FOR_PARTIAL_MATCHING, Gitlab::SQL::Pattern::REGEX_QUOTED_TERM

Constants inherited from ApplicationRecord

ApplicationRecord::MAX_PLUCK

Constants included from ResetOnUnionError

ResetOnUnionError::MAX_RESET_PERIOD

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Downloadable

#touch_last_downloaded_at

Methods included from Gitlab::SQL::Pattern

split_query_to_search_terms

Methods inherited from ApplicationRecord

cached_column_list, #create_or_load_association, declarative_enum, default_select_columns, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order

Methods included from SensitiveSerializableHash

#serializable_hash

Class Method Details

.by_file_name_and_sha256(file_name, sha256) ⇒ Object



248
249
250
251
# File 'app/models/packages/package.rb', line 248

def self.by_file_name_and_sha256(file_name, sha256)
  joins(:package_files)
    .where(packages_package_files: { file_name: file_name, file_sha256: sha256 }).last!
end

.by_name_and_file_name(name, file_name) ⇒ Object



242
243
244
245
246
# File 'app/models/packages/package.rb', line 242

def self.by_name_and_file_name(name, file_name)
  with_name(name)
    .joins(:package_files)
    .where(packages_package_files: { file_name: file_name }).last!
end

.by_name_and_version!(name, version) ⇒ Object



253
254
255
# File 'app/models/packages/package.rb', line 253

def self.by_name_and_version!(name, version)
  find_by!(name: name, version: version)
end

.debian_incoming_package!Object



257
258
259
# File 'app/models/packages/package.rb', line 257

def self.debian_incoming_package!
  find_by!(name: Packages::Debian::INCOMING_PACKAGE_NAME, version: nil, package_type: :debian, status: :default)
end

.existing_debian_packages_with(name:, version:) ⇒ Object



261
262
263
264
265
# File 'app/models/packages/package.rb', line 261

def self.existing_debian_packages_with(name:, version:)
  debian.with_name(name)
        .with_version(version)
        .not_pending_destruction
end

.inheritance_columnObject



221
# File 'app/models/packages/package.rb', line 221

def self.inheritance_column = 'package_type'

.inheritance_column_to_class_mapObject



223
224
225
# File 'app/models/packages/package.rb', line 223

def self.inheritance_column_to_class_map = {
  ml_model: 'Packages::MlModel::Package'
}.freeze

.keyset_pagination_order(join_class:, column_name:, direction: :asc) ⇒ Object



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'app/models/packages/package.rb', line 294

def self.keyset_pagination_order(join_class:, column_name:, direction: :asc)
  join_table = join_class.table_name
  asc_order_expression = join_class.arel_table[column_name].asc.nulls_last
  desc_order_expression = join_class.arel_table[column_name].desc.nulls_first
  order_direction = direction == :asc ? asc_order_expression : desc_order_expression
  reverse_order_direction = direction == :asc ? desc_order_expression : asc_order_expression
  arel_order_classes = ::Gitlab::Pagination::Keyset::ColumnOrderDefinition::AREL_ORDER_CLASSES.invert

  ::Gitlab::Pagination::Keyset::Order.build(
    [
      ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
        attribute_name: "#{join_table}_#{column_name}",
        column_expression: join_class.arel_table[column_name],
        order_expression: order_direction,
        reversed_order_expression: reverse_order_direction,
        order_direction: direction,
        distinct: false,
        add_to_projections: true
      ),
      ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
        attribute_name: 'id',
        order_expression: arel_order_classes[direction].new(Packages::Package.arel_table[:id]),
        add_to_projections: true
      )
    ])
end

.only_maven_packages_with_path(path, use_cte: false) ⇒ Object



227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'app/models/packages/package.rb', line 227

def self.only_maven_packages_with_path(path, use_cte: false)
  if use_cte
    # This is an optimization fence which assumes that looking up the Metadatum record by path (globally)
    # and then filter down the packages (by project or by group and subgroups) will be cheaper than
    # looking up all packages within a project or group and filter them by path.

    inner_query = Packages::Maven::Metadatum.where(path: path).select(:id, :package_id)
    cte = Gitlab::SQL::CTE.new(:maven_metadata_by_path, inner_query)
    with(cte.to_arel)
      .joins('INNER JOIN maven_metadata_by_path ON maven_metadata_by_path.package_id=packages_packages.id')
  else
    joins(:maven_metadatum).where(packages_maven_metadata: { path: path })
  end
end

.pluck_namesObject



267
268
269
# File 'app/models/packages/package.rb', line 267

def self.pluck_names
  pluck(:name)
end

.pluck_versionsObject



271
272
273
# File 'app/models/packages/package.rb', line 271

def self.pluck_versions
  pluck(:version)
end

.sort_by_attribute(method) ⇒ Object



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'app/models/packages/package.rb', line 275

def self.sort_by_attribute(method)
  case method.to_s
  when 'created_asc' then order_created
  when 'created_at_asc' then order_created
  when 'name_asc' then order_name
  when 'name_desc' then order_name_desc
  when 'version_asc' then order_version
  when 'version_desc' then order_version_desc
  when 'type_asc' then order_type
  when 'type_desc' then order_type_desc
  when 'project_name_asc' then order_project_name
  when 'project_name_desc' then order_project_name_desc
  when 'project_path_asc' then order_project_path
  when 'project_path_desc' then order_project_path_desc
  else
    order_created_desc
  end
end

Instance Method Details

#create_build_infos!(build) ⇒ Object



370
371
372
373
374
375
# File 'app/models/packages/package.rb', line 370

def create_build_infos!(build)
  return unless build&.pipeline

  # TODO: use an upsert call when https://gitlab.com/gitlab-org/gitlab/-/issues/339093 is implemented
  build_infos.find_or_create_by!(pipeline: build.pipeline)
end

#debian_incoming?Boolean

Returns:

  • (Boolean)


351
352
353
# File 'app/models/packages/package.rb', line 351

def debian_incoming?
  debian? && version.nil?
end

#debian_package?Boolean

Returns:

  • (Boolean)


355
356
357
# File 'app/models/packages/package.rb', line 355

def debian_package?
  debian? && !version.nil?
end

#infrastructure_package?Boolean

Returns:

  • (Boolean)


347
348
349
# File 'app/models/packages/package.rb', line 347

def infrastructure_package?
  terraform_module?
end

#last_build_infoObject

Technical debt: to be removed in gitlab.com/gitlab-org/gitlab/-/issues/281937



333
334
335
# File 'app/models/packages/package.rb', line 333

def last_build_info
  build_infos.last
end

#mark_package_files_for_destructionObject



377
378
379
380
381
# File 'app/models/packages/package.rb', line 377

def mark_package_files_for_destruction
  return unless pending_destruction?

  ::Packages::MarkPackageFilesForDestructionWorker.perform_async(id)
end

#normalized_nuget_versionObject



390
391
392
393
394
# File 'app/models/packages/package.rb', line 390

def normalized_nuget_version
  return unless nuget?

  nuget_metadatum&.normalized_version
end

#normalized_pypi_nameObject



384
385
386
387
388
# File 'app/models/packages/package.rb', line 384

def normalized_pypi_name
  return name unless pypi?

  name.gsub(/#{Gitlab::Regex::Packages::PYPI_NORMALIZED_NAME_REGEX_STRING}/o, '-').downcase
end

#package_settingsObject



359
360
361
# File 'app/models/packages/package.rb', line 359

def package_settings
  project.namespace.package_settings
end

#pipelineObject

Technical debt: to be removed in gitlab.com/gitlab-org/gitlab/-/issues/281937



339
340
341
# File 'app/models/packages/package.rb', line 339

def pipeline
  last_build_info&.pipeline
end

#publish_creation_eventObject



396
397
398
399
400
401
402
403
404
405
406
# File 'app/models/packages/package.rb', line 396

def publish_creation_event
  ::Gitlab::EventStore.publish(
    ::Packages::PackageCreatedEvent.new(data: {
      project_id: project_id,
      id: id,
      name: name,
      version: version,
      package_type: package_type
    })
  )
end

#sync_maven_metadata(user) ⇒ Object



364
365
366
367
368
# File 'app/models/packages/package.rb', line 364

def (user)
  return unless maven? && version? && user

  ::Packages::Maven::Metadata::SyncWorker.perform_async(user.id, project.id, name)
end

#tag_namesObject



343
344
345
# File 'app/models/packages/package.rb', line 343

def tag_names
  tags.pluck(:name)
end

#versionsObject



321
322
323
324
325
326
327
328
329
330
# File 'app/models/packages/package.rb', line 321

def versions
  project.packages
         .preload_pipelines
         .including_tags
         .displayable
         .with_name(name)
         .where.not(version: version)
         .with_package_type(package_type)
         .order(:version)
end