Class: Fastlane::Actions::AnnaiCompileBuildAction

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

Class Method Summary collapse

Class Method Details

.available_optionsObject


Define Parameters




142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_compile_build_action.rb', line 142

def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :platform,
                                 description: "The platform (:ios, :android, or :web)",
                                 is_string: false,
                                 verify_block: proc do |value|
                                    UI.user_error!("Platform must be :ios, :android, or :web") unless [:ios, :android, :web].include?(value)
                                 end),

    FastlaneCore::ConfigItem.new(key: :spec_file,
                                 description: "Path to the annai spec configuration file (relative to flutter root). Defaults to standard discovery",
                                 optional: true,
                                 default_value: nil),

    FastlaneCore::ConfigItem.new(key: :clean,
                                 description: "If true, runs annai_clean_build before compiling all flavors",
                                 type: Boolean,
                                 default_value: false),

    FastlaneCore::ConfigItem.new(key: :flavor,
                                 description: "The specific flavor(s) to build (comma-separated). If nil, all flavors are built",
                                 optional: true,
                                 default_value: nil),

    # All following options are passed directly to the single build action
    FastlaneCore::ConfigItem.new(key: :sub_command,
                                 description: "Flutter build subcommand (e.g., appbundle, ipa, web) to use for all flavors",
                                 # Note: If platform is :web, this should typically be 'web' or similar.
                                 default_value: "appbundle"),
    FastlaneCore::ConfigItem.new(key: :build_config,
                                 description: "Build configuration (e.g., debug, profile, release) to use for all flavors",
                                 default_value: "release"),
    FastlaneCore::ConfigItem.new(key: :main_file,
                                 description: "Path to the main dart file (used as default for all flavors unless overridden in the Annai spec)",
                                 default_value: "lib/main.dart"),
    FastlaneCore::ConfigItem.new(key: :skip_sound_null_safety,
                                 type: Boolean,
                                 default_value: false),
    FastlaneCore::ConfigItem.new(key: :skip_code_sign,
                                 type: Boolean,
                                 default_value: false),
    FastlaneCore::ConfigItem.new(key: :export_options_plist,
                                 description: "Path to export options plist (iOS only)",
                                 optional: true,
                                 default_value: ""),
    FastlaneCore::ConfigItem.new(key: :additional_parameter,
                                 description: "Additional flutter build parameters",
                                 optional: true,
                                 default_value: ""),
  ]
end

.descriptionObject



194
195
196
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_compile_build_action.rb', line 194

def self.description
  "Compiles all defined Flutter flavors for a single platform (:ios, :android, or :web) using the Annai spec configuration"
end

.example_codeObject



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_compile_build_action.rb', line 202

def self.example_code
  'ann_compile_build_all(
    platform: :android,
    spec_file: "config/my_annai.yaml", # Optional custom spec path
    build_config: "release",
    clean: true,
    flavor: "staging,production" # Optional comma-separated list
  )
  ann_compile_build_all(
    platform: :web,
    sub_command: "web", # Specify the web subcommand
    build_config: "release",
    flavor: "test_web"
  )'
end

.is_supported?(platform) ⇒ Boolean

Returns:

  • (Boolean)


198
199
200
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_compile_build_action.rb', line 198

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

.run(params) ⇒ Object



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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_compile_build_action.rb', line 9

def self.run(params)
  platform = params[:platform]
  requested_flavor = params[:flavor]
  requested_clean_build = params[:clean]
  spec_file = params[:spec_file]

  # 1. Initialize AnnaiLanes
  annai_lanes = FastlaneFlutterFlavor::AnnaiLanes.new(
    lane: self,
    platform: platform, # Pass platform symbol directly
    spec_file: spec_file # Pass optional spec_file
  )

  # Get the StatusManager instance for logging errors explicitly
  status_manager = annai_lanes.instance_variable_get(:@statusManager)

  spec_loader = annai_lanes.instance_variable_get(:@specLoader)
  UI.user_error!("Internal Error: AnnaiLanes failed to initialize specLoader.") unless spec_loader

  # Flag to track if any flavor compilation failed
  any_build_failed = false

  # 2. Perform clean build if requested
  if requested_clean_build
      UI.header("🧹 Cleaning builds as requested...")
      begin
        annai_lanes.clean_build
      rescue => e
        UI.error("Failed to perform clean build: #{e.message}. Attempting to proceed with compilation.")
        status_manager.logError("All", "annai_clean_build", platform, "Clean build failed: #{e.message}")
      end
  end

  # 3. Get the list of all flavors defined for the platform
  flavors_hash = spec_loader.get_platform_flavors(platform)

  if flavors_hash.empty?
    UI.important("No flavors found for platform '#{platform}' in the Annai spec. Nothing to build.")
    annai_lanes.finalize
    return
  end

  all_flavor_names = flavors_hash.keys

  # 4. Determine which flavors to build
  if requested_flavor && !requested_flavor.to_s.empty?
      requested_flavors = requested_flavor.to_s.split(',').map(&:strip).reject(&:empty?)

      # Validate all requested flavors
      invalid_flavors = requested_flavors.reject { |f| all_flavor_names.include?(f) }

      if invalid_flavors.any?
          UI.user_error!("The following requested flavor(s) are not found in the Annai spec for platform '#{platform}': #{invalid_flavors.join(', ')}. Available flavors: #{all_flavor_names.join(', ')}")
      end

      flavors_to_build = requested_flavors

  else
      # No specific flavor requested, build all of them
      flavors_to_build = all_flavor_names
  end

  UI.header("Starting build for #{platform}. Flavors to compile: #{flavors_to_build.join(', ')}")


  # 5. Loop through each flavor and directly call compile_build on AnnaiLanes
  flavors_to_build.each do |flavor_key|

    flavor = flavor_key.to_s

    # Use the new getter, which uses the internal spec data
    flavor_main_file = spec_loader.get_main_file(platform, flavor)

    # Use the main_file provided by the user as a fallback if the spec doesn't define one
    final_main_file = flavor_main_file || params[:main_file]

    if final_main_file.nil? || final_main_file.empty?
      error_msg = "Could not determine 'main_file' for flavor '#{flavor}' on platform '#{platform}'. Check your Annai spec or provide a default 'main_file'."
      UI.error("#{error_msg}")
      status_manager.logError(flavor, "ann_compile_build_all", platform, error_msg)
      any_build_failed = true
      next
    end

    UI.message("⚙️ Compiling **#{flavor}** flavor using main file: #{final_main_file}...")

    begin
      # CRITICAL: Direct call to the AnnaiLanes helper method
      success = annai_lanes.compile_build(
        flavor: flavor,
        sub_command: params[:sub_command],
        build_config: params[:build_config],
        main_file: final_main_file,
        skip_sound_null_safety: params[:skip_sound_null_safety],
        skip_code_sign: params[:skip_code_sign],
        export_options_plist: params[:export_options_plist],
        additional_parameter: params[:additional_parameter],
        platform: platform.to_s # Ensure platform is passed as a string/symbol as expected by the helper
      )

      if success
        UI.success("🎉 Successfully compiled flavor: #{flavor}")
      else
        # If compile_build returns false (meaning it caught an error and logged it), flag the overall failure.
        raise "Compilation failed for flavor '#{flavor}' (error logged previously)."
      end
    rescue => e
      # Failure handling: Log the error using StatusManager (if not already logged by compile_build) and continue
      if !status_manager.instance_variable_get(:@status).key?([flavor, "compile_build", platform.to_s])
        status_manager.logError(flavor, "ann_compile_build_all", platform, e.message)
      end

      UI.error("❌ Failed to compile flavor: #{flavor}. Continuing to next flavor...")
      any_build_failed = true
      # Continue to the next flavor
    end
  end

  # 6. Final Reporting and Status Check
  # Finalize calls statusManager.displayStatus to show the comprehensive report
  annai_lanes.finalize

  if any_build_failed
      # If any build failed, we stop the lane with an error after the summary is displayed.
      UI.user_error!("Compilation failed for one or more flavors. See the Annai Fastlane summary above.")
  else
      UI.success("✅ Successfully compiled all #{flavors_to_build.count} requested flavor(s) for #{platform}!")
  end
end