BigW Consortium Gitlab

20161207231626_add_environment_slug.rb 1.97 KB
Newer Older
Nick Thomas committed
1 2 3 4 5 6 7 8 9 10
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.

class AddEnvironmentSlug < ActiveRecord::Migration
  include Gitlab::Database::MigrationHelpers

  DOWNTIME = true
  DOWNTIME_REASON = 'Adding NOT NULL column environments.slug with dependent data'

  # Used to generate random suffixes for the slug
11
  LETTERS = 'a'..'z'
Nick Thomas committed
12
  NUMBERS = '0'..'9'
13
  SUFFIX_CHARS = LETTERS.to_a + NUMBERS.to_a
Nick Thomas committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

  def up
    environments = Arel::Table.new(:environments)

    add_column :environments, :slug, :string
    finder = environments.project(:id, :name)

    connection.exec_query(finder.to_sql).rows.each do |id, name|
      updater = Arel::UpdateManager.new(ActiveRecord::Base).
        table(environments).
        set(environments[:slug] => generate_slug(name)).
        where(environments[:id].eq(id))

      connection.exec_update(updater.to_sql, self.class.name, [])
    end

    change_column_null :environments, :slug, false
  end

  def down
    remove_column :environments, :slug
  end

  # Copy of the Environment#generate_slug implementation
  def generate_slug(name)
    # Lowercase letters and numbers only
    slugified = name.to_s.downcase.gsub(/[^a-z0-9]/, '-')

    # Must start with a letter
43 44 45 46
    slugified = 'env-' + slugified unless LETTERS.cover?(slugified[0])

    # Repeated dashes are invalid (OpenShift limitation)
    slugified.gsub!(/\-+/, '-')
Nick Thomas committed
47 48 49 50

    # Maximum length: 24 characters (OpenShift limitation)
    slugified = slugified[0..23]

51 52
    # Cannot end with a dash (Kubernetes label limitation)
    slugified.chop! if slugified.end_with?('-')
Nick Thomas committed
53 54 55

    # Add a random suffix, shortening the current string if necessary, if it
    # has been slugified. This ensures uniqueness.
56 57 58 59 60
    if slugified != name
      slugified = slugified[0..16]
      slugified << '-' unless slugified.end_with?('-')
      slugified << random_suffix
    end
Nick Thomas committed
61 62 63 64 65 66 67 68

    slugified
  end

  def random_suffix
    (0..5).map { SUFFIX_CHARS.sample }.join
  end
end