Swap bigint columns for deployments phase two
What does this MR do and why?
Phase two of the deployments bigint conversion covers the project_id and
user_id columns. This MR swaps them with their _convert_to_bigint
counterparts, along with the associated indexes and the outbound foreign key.
Everything upstream is in place: the columns are backfilled, the bigint indexes
exist, and fk_b9a3851b82_tmp is validated
(!247870 (merged)).
This mirrors SwapColumnsForDeploymentsBigintConversionPhaseOne
(db/post_migrate/20260319230449),
which shipped in 18.11 via
!221371 (merged).
Every index swap is guarded
swap_indexes renames unconditionally, and rename_index_with_schema issues a
bare ALTER INDEX ... RENAME TO that raises when the index is absent. Phase one
hit exactly this in production and was patched three times:
Each added an index_exists_by_name? check, but only around the
self-managed-only index. This MR applies that check to all eight indexes from
the start, through a single swap_index_if_exists helper, which removes the
whole class of failure rather than the one instance that happened to break.
The Gitlab.com_except_jh? guard alone is not sufficient: it correctly skips
GitLab.com, but on a self-managed installation that never ran
RecreateDeploymentIndexes the index can still be missing, and that is the case
phase one tripped over.
index_deployments_on_user_id_and_status_and_created_at is the index in
question here. It was dropped on GitLab.com in
!157136 (merged) because it had zero
scans over 30 days, but kept for self-managed, where UsageData and
CountDeploymentsMetric still need it. It is recorded as a
schema_inconsistencies entry in db/docs/deployments.yml.
Current production state
Column | Type | Nullable | Default
----------------------------------+---------+----------+---------
id | bigint | not null | nextval(...)
id_convert_to_bigint | integer | not null | 0
project_id | integer | not null |
project_id_convert_to_bigint | bigint | not null | 0
environment_id | bigint | not null | 0
environment_id_convert_to_bigint | integer | not null |
user_id | integer | |
user_id_convert_to_bigint | bigint | |
Indexes:
"deployments_pkey" PRIMARY KEY, btree (id)
"bigint_idx_4745a7ef0582f322e2f1" btree (project_id_convert_to_bigint, status, created_at)
"bigint_idx_4c8e0f9c13ac7d521d9d" btree (archived, project_id_convert_to_bigint, iid)
"bigint_idx_b590ec5161feccd7566b" btree (project_id_convert_to_bigint, id DESC)
"bigint_idx_d8cb85cd6cae740bdadd" btree (project_id_convert_to_bigint, environment_id, updated_at, id)
"bigint_idx_edd8d74fd9e28dac7675" UNIQUE, btree (project_id_convert_to_bigint, iid)
"bigint_idx_f88f5fd861fda452cfae" btree (project_id_convert_to_bigint, updated_at DESC, id DESC)
"bigint_idx_fa0a59fb88e847edcf95" btree (project_id_convert_to_bigint, finished_at) WHERE status = 2
Foreign-key constraints:
"fk_b9a3851b82" FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
"fk_b9a3851b82_tmp" FOREIGN KEY (project_id_convert_to_bigint) REFERENCES projects(id) ON DELETE CASCADEAll seven project_id bigint indexes are present. The eighth,
bigint_idx_ed4028e09bf8233731e7 for user_id, is correctly absent on
GitLab.com, as described above.
Not in this MR
Dropping the temporary indexes and the temporary foreign key, mirroring
db/post_migrate/20260319230454.
Once that lands, #551605 (drop the trigger and the old integer columns) unblocks for the following milestone.
Verification
db/structure.sql is unchanged. A schema built from structure.sql has no
_convert_to_bigint columns, so the migration self-skips locally and a local
run proves nothing — this is precisely how the phase one failure reached
production. The database-testing-automation job against a production-like
clone is the meaningful check here.
References
- Related to #551602
- Epic: &20032
- Validates the FK swapped here: !247870 (merged)
- Phase one swap: !221371 (merged)
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.