Class: Fastlane::Actions::ValidateXcconfigAction

Inherits:
Action
  • Object
show all
Defined in:
lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb

Overview

Action for validating Xcconfig files.

Implementation collapse

Info and Options collapse

Class Method Summary collapse

Class Method Details

.authorsObject

Plugin action authors.



82
83
84
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 82

def self.authors
  ["Maksym Grebenets"]
end

.available_optionsObject

Plugin action available options.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 109

def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :path,
                            env_name: "XCCONFIG_ACTIONS_VALIDATE_PATH",
                         description: "Path to xcconfig to validate",
                            optional: false,
                                type: String,
                        verify_block: proc do |value|
                                        UI.user_error!("Couldn't find xcconfig at path: '#{value}'") unless File.exist?(value)
                                      end),
    FastlaneCore::ConfigItem.new(key: :root_path,
                            env_name: "XCCONFIG_ACTIONS_VALIDATE_ROOT_PATH",
                         description: "Root path for all xcconfigs validated with this action",
                            optional: false,
                                type: String,
                        verify_block: proc do |value|
                                        UI.user_error!("Couldn't find root xcconfig directory: '#{value}'") unless File.exist?(value)
                                      end)
  ]
end

.categoryObject

Plugin action category.



104
105
106
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 104

def self.category
  :linting
end

.descriptionObject

Plugin action description.



77
78
79
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 77

def self.description
  "Validate xcconfig file"
end

.detailsObject

Plugin action details.



92
93
94
95
96
97
98
99
100
101
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 92

def self.details
  [
    "Validation rules:",
    "- All included files exist",
    "- Include flow is unidirectional, i.e. top-down only",
    "- Files do not include other files on the same level",
    "- Files do not include other files more than 1 level down",
    "- Files do not contain duplicate includes"
  ].join("\n")
end

.is_supported?(platform) ⇒ Boolean

Check if platform is supported by the action.

Parameters:

  • platform (Symbol)

    Platform to check.

Returns:

  • (Boolean)

    A Boolean indicating whether the platform is supported by the action.



133
134
135
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 133

def self.is_supported?(platform)
  [:ios, :mac].include?(platform)
end

.return_valueObject

Plugin action return value.



87
88
89
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 87

def self.return_value
  "List of validation issues"
end

.run(params) ⇒ Array<String>

Run action.

Parameters:

  • params (Hash)

    Action parameters.

Returns:

  • (Array<String>)

    List of validation issues.



11
12
13
14
15
16
17
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 11

def self.run(params)
  path = params[:path]
  root_path = params[:root_path]

  # Validate configs recursively.
  validate_xcconfig(path, root_path: root_path, included_paths: [path], level: 0)
end

.validate_include_path(path, xcconfig:) ⇒ Array<String>

Validate xcconfig include path.

Parameters:

  • path (String)

    include path to validate.

  • xcconfig (String)

    path to xcconfig being validated.

Returns:

  • (Array<String>)

    list of issues.



64
65
66
67
68
69
70
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 64

def self.validate_include_path(path, xcconfig:)
  issues = []
  issues << "#{xcconfig}: Invalid bottom-up include flow, i.e. use of '..' in include path: #{path}" if path.include?("..")
  issues << "#{xcconfig}: Including another xcconfig 2 or more levels down: #{path}" if path.count("/") > 1
  issues << "#{xcconfig}: Including another xcconfig on the same level: #{path}" if path.count("/") < 1
  issues
end

.validate_xcconfig(xcconfig, root_path:, included_paths: [], level: 0) ⇒ Array<String>

Validate xcconfig file.

Parameters:

  • xcconfig (String)

    Path to xcconfig.

  • root_path (String)

    Root path for all xcconfigs validated in this method.

  • included_paths (Array<String>) (defaults to: [])

    List of files included so far, used to detect circular includes.

  • level (Int) (defaults to: 0)

    Nesting level of xcconfig.

Returns:

  • (Array<String>)

    list of issues.



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
# File 'lib/fastlane/plugin/xcconfig_actions/actions/validate_xcconfig_action.rb', line 29

def self.validate_xcconfig(xcconfig, root_path:, included_paths: [], level: 0)
  require "pathname"

  relative_path = Pathname.new(xcconfig).relative_path_from(Pathname.new(root_path))
  return ["File does not exist or is a directory: #{xcconfig}"] unless File.exist?(xcconfig) && File.file?(xcconfig)

  config = Helper::XcconfigActionsHelper.read_xcconfig(xcconfig)
  includes = config[:includes]

  issues = includes.flat_map { |include_path| validate_include_path(include_path, xcconfig: relative_path) }
  dupes = includes.select { |e| includes.count(e) > 1 }.uniq
  issues << " #{relative_path}: Duplicate includes detected: #{dupes.join('\n')}" unless dupes.nil? || dupes.empty?
  full_paths = includes.map { |path| Pathname.new(File.join(File.dirname(xcconfig), path)).cleanpath }
  common_paths = included_paths & full_paths
  unless common_paths.empty?
    common_paths_string = common_paths.map { |p| "  - #{p}" }.join("\n")
    issues << "#{relative_path}: Circular includes detected, check the following files:\n#{common_paths_string}"
  end

  result = issues.empty? ? "" : ""
  offset = " " * 4 * level + " └──"
  UI.message("#{offset} #{result} #{relative_path}")

  # If circular includes detected stop the recursion.
  return issues unless common_paths.empty?

  # Recursively validate the rest.
  issues + full_paths.flat_map { |path| validate_xcconfig(path, root_path: root_path, included_paths: included_paths + full_paths, level: level + 1) }
end