-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
configure_feature_flags.rb
90 lines (73 loc) · 2.96 KB
/
configure_feature_flags.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/env ruby
require "optparse"
require "set"
# sameersbn/docker-gitlab
# Ruby script to configure feature flags via CLI
# Intended to be executed in the context of Rails Runner of Gitlab application
# (to get valid "Feature" module, defined in (gitlab root)/lib/feature.rb)
# https://guides.rubyonrails.org/command_line.html#bin-rails-runner
# bundle exec rails runner <path to this script> -- --enable <enable target> --disable <disable target>
class FeatureFlagCLI
def available_feature_flags()
# Feature flag lists are stored in (Gitlab root directory)/config/feature_flags/
# We can get the directory by accessing "root" property of "Gitlab" Module
# (may returns /home/git/gitlab for sameersbn/docker-gitlab)
feature_flag_yamls = Dir.glob("#{Gitlab.root}/config/feature_flags/**/*.yml")
if Gitlab.ee?
feature_flag_yamls.concat(Dir.glob("#{Gitlab.root}/ee/config/feature_flags/**/*.yml"))
end if
list = feature_flag_yamls.map { |p| File.basename(p, File.extname(p)) }
list
end
def parse_options(argv = ARGV)
op = OptionParser.new
opts = {
to_be_disabled: [],
to_be_enabled: [],
# TODO support "opt out", "opt out removed"
# to_be_opted_out: [],
# opt_out_removed: [],
}
op.on("-d", "--disable feature_a,feature_b,feature_c", Array, "comma-separated list of feature flags to be disabled (defaults: ${opts[:to_be_disabled]})") { |v|
opts[:to_be_disabled] = v.uniq
}
op.on("-e", "--enable feature_a,feature_b,feature_c", Array, "comma-separated list of feature flags to be enabled (defaults: ${opts[:to_be_enabled]})") { |v|
opts[:to_be_enabled] = v.uniq
}
begin
args = op.parse(argv)
succeed = true
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
puts e.message
puts op.help
succeed = false
end
[succeed, opts, args]
end
def run
succeed, opts, args = parse_options
if succeed
puts "- specified feature flags: #{opts.to_s}"
available_flags = self.available_feature_flags
disable_targets = available_flags & opts[:to_be_disabled]
enable_targets = available_flags & opts[:to_be_disabled]
disable_targets.each do |feature|
Feature.disable(feature)
end
enable_targets.each do |feature|
Feature.enable(feature)
end
invalid_enable_targets = opts[:to_be_enabled] - enable_targets
invalid_disable_targets = opts[:to_be_disabled] - disable_targets
invalid_targets = invalid_disable_targets | invalid_enable_targets
if invalid_targets.length > 0
puts "- Following flags are probably invalid and have been ignored: #{invalid_enable_targets.to_a.join(",")}"
end
end
Feature.all
end
end
features = FeatureFlagCLI.new.run
puts features.map { |f|
format("- feature %<name>s : %<state>s", name: f.name, state: f.state)
}