summaryrefslogtreecommitdiff
path: root/scripts/changed-feature-flags
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/changed-feature-flags')
-rwxr-xr-xscripts/changed-feature-flags75
1 files changed, 65 insertions, 10 deletions
diff --git a/scripts/changed-feature-flags b/scripts/changed-feature-flags
index 3a4f18bd78f..86214e86788 100755
--- a/scripts/changed-feature-flags
+++ b/scripts/changed-feature-flags
@@ -3,10 +3,12 @@
require 'yaml'
require 'optparse'
+require 'pathname'
require_relative 'api/default_options'
# This script returns the desired feature flag state as a comma-separated string for the feature flags in the specified files.
-# Each desired feature flag state is specified as 'feature-flag=state'.
+# Each desired feature flag state is specified as 'feature-flag=state'. This allows us to run package-and-qa with the
+# feature flag set to the desired state.
#
# For example, if the specified files included `config/feature_flags/development/ci_yaml_limit_size.yml` and the desired
# state as specified by the second argument was enabled, the value returned would be `ci_yaml_limit_size=enabled`
@@ -15,31 +17,84 @@ class GetFeatureFlagsFromFiles
def initialize(options)
@files = options.delete(:files)
@state = options.delete(:state)
+
+ abort("ERROR: Please specify the directory containing MR diffs.") if @files.to_s.empty?
end
+ # Gets feature flags from definition files or diffs of deleted defition files
+ #
+ # @return [String] a comma-separated list of feature flags and their desired state
def extracted_flags
- files.each_with_object([]) do |file_path, all|
- next unless file_path =~ %r{/feature_flags/(development|ops)/.*\.yml}
- next unless File.exist?(file_path)
+ flags_list = diffs_dir.glob('**/*').each_with_object([]) do |file_path, flags|
+ ff_yaml = ff_yaml_for_file(file_path)
+ next if ff_yaml.nil?
+ break [] if ff_yaml.empty?
+
+ flags << ff_yaml['name']
+ end
+ flags_list = flags_list.map { |flag| "#{flag}=#{state}" } unless state.to_s.empty?
+ flags_list.join(',')
+ end
- ff_yaml = YAML.safe_load(File.read(file_path))
- ff_to_add = "#{ff_yaml['name']}"
- ff_to_add += "=#{state}" unless state.to_s.empty?
+ # Loads the YAML feature flag definition based on a diff of the definition file. The definition is loaded from the
+ # definition file itself, or from a diff of the deleted definition file.
+ #
+ # @param [Pathname] path the path to the diff
+ # @return [Hash] a hash containing the YAML data for the feature flag definition
+ def ff_yaml_for_file(path)
+ return unless File.expand_path(path).to_s =~ %r{/feature_flags/(development|ops)/.*\.yml}
- all << ff_to_add
- end.join(',')
+ if path.to_s.end_with?('yml.deleted.diff')
+ # Ignore deleted feature flag definitions if we want to enable/disable existing flags.
+ return if state != 'deleted'
+
+ yaml_from_deleted_diff(path)
+ else
+ # If we want deleted definition files but find one that wasn't deleted, we return immediately to
+ # because non-deleted flags are tested in separate jobs from deleted flags, so we don't need to run
+ # a job with just deleted flags.
+ return [] if state == 'deleted'
+
+ yaml_from_file(path, diffs_dir)
+ end
end
private
attr_reader :files, :state
+
+ # The absolute path to the directory of diffs
+ #
+ # @return [String]
+ def diffs_dir
+ @diffs_dir ||= Pathname.new(files).expand_path
+ end
+
+ # Loads the YAML feature flag definition from a file corresponding to a diff of the definition file.
+ #
+ # @param [Pathname] file_path the path to the diff
+ # @param [Pathname] diffs_dir the path to the diffs directory
+ # @return [Hash] a hash containing the YAML data from the feature flag definition file corresponding to the diff
+ def yaml_from_file(file_path, diffs_dir)
+ real_file_path = File.join(Dir.pwd, file_path.to_s.delete_prefix(diffs_dir.to_s)).delete_suffix('.diff')
+ YAML.safe_load(File.read(real_file_path))
+ end
+
+ # Loads the YAML feature flag definition from a diff of the deleted feature flag definition file.
+ #
+ # @param [Pathname] file_path the path of the diff
+ # @return [Hash] a hash containing the YAML data for the feature flag definition from the diff
+ def yaml_from_deleted_diff(file_path)
+ cleaned_diff = File.read(file_path).gsub(/^[^a-z]+/, '')
+ YAML.safe_load(cleaned_diff)
+ end
end
if $0 == __FILE__
options = API::DEFAULT_OPTIONS.dup
OptionParser.new do |opts|
- opts.on("-f", "--files FILES", Array, "Comma-separated list of feature flag config files") do |value|
+ opts.on("-f", "--files FILES", String, "A directory containing diffs including feature flag definition change diffs") do |value|
options[:files] = value
end