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
Related Issues
- Parent issue: #583031 (Database schema inconsistency for CI build name fields)