Application settings development
This document provides a development guide for contributors to add application settings to GitLab.
Application settings are stored in the application_settings
table. Each setting has its own column and there should only be one row.
Add a new application setting
First of all, you have to decide if it is necessary to add an application setting. Consider our configuration principles when adding a new setting.
We prefer saving the related application settings in a single JSONB column to avoid making the application_settings
table wider. Also, adding a new setting to an existing column doesn't require a database review so it saves time.
To add a new setting, you have to:
- Check if there is an existing JSONB column that you can use to store the new setting.
- If there is an existing JSON column then:
- Add new setting to the JSONB column like
rate_limits
in theApplicationSetting
model. - Update the JSON schema validator for the column like
rate_limits
validator.
- Add new setting to the JSONB column like
- If there isn't an existing JSON column which you can use then:
- Add a new JSON column to the
application_settings
table to store, see this merge request for reference. - Add a constraint to ensure the column always stores a hash, see this merge request for reference.
- Create follow-up issues to move existing related columns to this newly created JSONB column. Follow the process to migrate a database columns to a JSONB column.
- Add a new JSON column to the
- Add the new setting to the list of visible attributes.
- Add the new setting to it to
ApplicationSettingImplementation#defaults
, if the setting has a default value. - Add a test for the default value, if the setting has a default value.
- Add a validation for the new field to the
ApplicationSetting
model. - Add a model test for the validation and default value
- Find the right view file or create a new one and add a form field to the new setting.
- Update the API documentation. Application settings are automatically made available on the REST API.
- Run the
scripts/cells/application-settings-analysis.rb
script to generate a definition YAML file atconfig/application_setting_columns/*.yml
and update the documentation file atcells/application_settings_analysis
, based ondb/structure.sql
and the API documentation. After the definition file is created, ensure you set theclusterwide
key totrue
orfalse
in it. Settingclusterwide: true
means that the attribute value are copied from the leader cell to other cells in the context of Cells architecture. In most cases,clusterwide: false
is preferable.
Database migration example
class AddNewSetting < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
with_lock_retries do
add_column :application_settings, :new_setting, :text, if_not_exists: true
end
add_text_limit :application_settings, :new_setting, 255
end
def down
with_lock_retries do
remove_column :application_settings, :new_setting, if_exists: true
end
end
end
Model validation example
validates :new_setting,
length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
allow_blank: true
Migrate a database column to a JSONB column
To migrate a column to JSONB, add the new setting under the JSONB accessor. Follow the process to add a new application setting.
You can use the same name as the existing column to maintain consistency. During the transition period, Rails writes the same information to both the existing database column and the field under the new JSONB column. This ensures data consistency and prevents downtime.
You must follow the process for dropping columns to remove the original column. This a required multi-milestone process that involves:
- Ignoring the column.
- Dropping the column.
- Removing the ignore rule.
Dropping the original column before ignoring it in the model can cause problems with zero-downtime migrations.