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 won’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 the ApplicationSetting model.
    • Update the JSON schema validator for the column like rate_limits validator.
  • 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.
  • 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 will automatically be available on the REST API.

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