gitlab-org--gitlab-foss/lib/gitlab/slug/environment.rb
Tiger 41fc4d1e44 Introduce predictable environment slugs
If an environment slug is predictable given only the environment
name, we can use the environment slug earlier in the CI variable
evaluation process as we don't have to wait for the environment
record itself to be persisted.
2019-07-19 11:33:07 +10:00

58 lines
1.7 KiB
Ruby

# frozen_string_literal: true
# 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 `-`
module Gitlab
module Slug
class Environment
attr_reader :name
def initialize(name)
@name = name
end
def generate
# Lowercase letters and numbers only
slugified = name.to_s.downcase.gsub(/[^a-z0-9]/, '-')
# Must start with a letter
slugified = 'env-' + slugified unless slugified.match?(/^[a-z]/)
# Repeated dashes are invalid (OpenShift limitation)
slugified.squeeze!('-')
slugified =
if slugified.size > 24 || slugified != name
# Maximum length: 24 characters (OpenShift limitation)
shorten_and_add_suffix(slugified)
else
# Cannot end with a dash (Kubernetes label limitation)
slugified.chomp('-')
end
slugified
end
private
def shorten_and_add_suffix(slug)
slug = slug[0..16]
slug << '-' unless slug.ends_with?('-')
slug << suffix
end
# Slugifying a name may remove the uniqueness guarantee afforded by it being
# based on name (which must be unique). To compensate, we add a predictable
# 6-byte suffix in those circumstances. This is not *guaranteed* uniqueness,
# but the chance of collisions is vanishingly small
def suffix
Digest::SHA2.hexdigest(name.to_s).to_i(16).to_s(36).last(6)
end
end
end
end