UpdateBuildNamesService bypasses name truncation when using upsert_all

Summary

The Ci::UpdateBuildNamesService uses upsert_all to insert/update build names, which bypasses the Ci::BuildName model's name= setter that truncates values to 255 characters (MAX_JOB_NAME_LENGTH). This can lead to database constraint violations or inconsistent data when build names exceed the limit.

Current Behavior

In app/models/ci/build_name.rb, the model defines:

MAX_JOB_NAME_LENGTH = 255

def name=(value)
  super(value&.truncate(MAX_JOB_NAME_LENGTH))
end

However, app/services/ci/update_build_names_service.rb uses:

Ci::BuildName.upsert_all(builds_upsert_data, unique_by: [:build_id, :partition_id])

Since upsert_all doesn't instantiate records, it bypasses the name= setter, meaning names longer than 255 characters are not truncated.

Expected Behavior

Build names should be truncated to MAX_JOB_NAME_LENGTH (255 characters) before being passed to upsert_all to ensure data consistency and prevent potential database constraint violations.

Proposed Solution

Truncate the name field in the upsert_records method before calling upsert_all:

builds_upsert_data =
  batch
    .pluck(:id, :partition_id, :name, :project_id)
    .map do |values|
      data = Hash[keys.zip(values)]
      data[:name] = data[:name]&.truncate(Ci::BuildName::MAX_JOB_NAME_LENGTH)
      data
    end
  • Parent issue: #583031 (Database schema inconsistency for CI build name fields)
Edited by 🤖 GitLab Bot 🤖