diff options
author | Nick Thomas <nick@gitlab.com> | 2016-12-08 04:09:18 +0300 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2016-12-15 16:57:03 +0300 |
commit | 93a03cd92f6418fbeaf126c30c161ab40d377e94 (patch) | |
tree | 0f49cd51558b97b8674e72b200e7d9150562e00e /app/models/environment.rb | |
parent | 35a3e9183052bab847c30203f27fea9cf77901a4 (diff) |
Add an environment slug
Diffstat (limited to 'app/models/environment.rb')
-rw-r--r-- | app/models/environment.rb | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/app/models/environment.rb b/app/models/environment.rb index 96700143ddd..0abbf674b9d 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -1,9 +1,15 @@ class Environment < ActiveRecord::Base + # Used to generate random suffixes for the slug + NUMBERS = '0'..'9' + SUFFIX_CHARS = ('a'..'z').to_a + NUMBERS.to_a + belongs_to :project, required: true, validate: true has_many :deployments before_validation :nullify_external_url + before_validation :generate_slug, if: ->(env) { env.slug.blank? } + before_save :set_environment_type validates :name, @@ -13,6 +19,13 @@ class Environment < ActiveRecord::Base format: { with: Gitlab::Regex.environment_name_regex, message: Gitlab::Regex.environment_name_regex_message } + validates :slug, + presence: true, + uniqueness: { scope: :project_id }, + length: { maximum: 24 }, + format: { with: Gitlab::Regex.environment_slug_regex, + message: Gitlab::Regex.environment_slug_regex_message } + validates :external_url, uniqueness: { scope: :project_id }, length: { maximum: 255 }, @@ -107,4 +120,41 @@ class Environment < ActiveRecord::Base action.expanded_environment_name == environment end end + + # An environment name is not necessarily suitable for use in URLs, DNS + # or other third-party contexts, so provide a slugified version. A slug has + # the following properties: + # * contains only lowercase letters (a-z), numbers (0-9), and '-' + # * begins with a letter + # * has a maximum length of 24 bytes (OpenShift limitation) + # * cannot end with `-` + def generate_slug + # Lowercase letters and numbers only + slugified = name.to_s.downcase.gsub(/[^a-z0-9]/, '-') + + # Must start with a letter + slugified = "env-" + slugified if NUMBERS.cover?(slugified[0]) + + # Maximum length: 24 characters (OpenShift limitation) + slugified = slugified[0..23] + + # Cannot end with a "-" character (Kubernetes label limitation) + slugified = slugified[0..-2] if slugified[-1] == "-" + + # Add a random suffix, shortening the current string if necessary, if it + # has been slugified. This ensures uniqueness. + slugified = slugified[0..16] + "-" + random_suffix if slugified != name + + self.slug = slugified + end + + private + + # Slugifying a name may remove the uniqueness guarantee afforded by it being + # based on name (which must be unique). To compensate, we add a random + # 6-byte suffix in those circumstances. This is not *guaranteed* uniqueness, + # but the chance of collisions is vanishingly small + def random_suffix + (0..5).map { SUFFIX_CHARS.sample }.join + end end |