Class: Fastlane::Actions::AnnaiDownloadFromAppStoreAction

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

Overview

This class name dictates the action name ‘ann_download_from_app_store’

Class Method Summary collapse

Class Method Details

.available_optionsObject


Define Parameters




121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_download_from_app_store_action.rb', line 121

def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :flavor,
                                 description: "The specific flavor(s) to download (comma-separated). If nil, all flavors are processed",
                                 optional: true,
                                 default_value: nil),

    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: :api_key_path,
                                 description: "Path to the App Store Connect API Key JSON file (iOS). Optional if defined in the Annai spec",
                                 optional: true,
                                 default_value: nil),
    FastlaneCore::ConfigItem.new(key: :package_name,
                                 description: "The bundle identifier (iOS). Optional if defined in the Annai spec",
                                 optional: true,
                                 default_value: nil),

    FastlaneCore::ConfigItem.new(key: :distribution_platform,
                                 description: "The distribution platform (e.g., 'ios' or 'app_store_connect') for App Store uploads",
                                 optional: true,
                                 default_value: "ios"),

    FastlaneCore::ConfigItem.new(key: :metadata_path,
                                 description: "The path where localization metadata (e.g., descriptions, titles) should be downloaded",
                                 optional: true,
                                 default_value: nil),
    FastlaneCore::ConfigItem.new(key: :screenshots_path,
                                 description: "The path where screenshots should be downloaded (iOS only)",
                                 optional: true,
                                 default_value: nil),

    FastlaneCore::ConfigItem.new(key: :use_live_version,
                                 description: "If true, downloads the currently published live version. If false (default), downloads the editable version (iOS only)",
                                 optional: true,
                                 type: Boolean,
                                 default_value: false),
  ].compact
end

.descriptionObject



164
165
166
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_download_from_app_store_action.rb', line 164

def self.description
  "Downloads store metadata, screenshots, and other assets for one or all flavors from the Apple App Store"
end

.example_codeObject



172
173
174
175
176
177
178
179
180
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_download_from_app_store_action.rb', line 172

def self.example_code
  'ann_download_from_app_store(
    flavor: "production",
    spec_file: "config/annai_config.yaml", # Optional custom spec path
    api_key_path: "./api_keys/asc.json",
    package_name: "com.example.app",
    use_live_version: true
  )'
end

.is_supported?(platform) ⇒ Boolean

Returns:

  • (Boolean)


168
169
170
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_download_from_app_store_action.rb', line 168

def self.is_supported?(platform)
  platform == :ios
end

.run(params) ⇒ Object



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
# File 'lib/fastlane/plugin/ann_flutter_flavor/actions/ann_download_from_app_store_action.rb', line 10

def self.run(params)
  # Platform is hardcoded to :ios
  platform = :ios
  action_name = "ann_download_from_app_store"
  requested_flavor = params[:flavor]
  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 and SpecLoader instances
  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 download failed
  any_download_failed = false

  # 2. 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 iOS in the Annai spec. Nothing to download")
    annai_lanes.finalize
    return
  end

  all_flavor_names = flavors_hash.keys

  # 3. Determine which flavors to download
  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 IOS: #{invalid_flavors.join(', ')}. Available flavors: #{all_flavor_names.join(', ')}")
      end

      flavors_to_download = requested_flavors
  else
      # No specific flavor requested, download all of them
      flavors_to_download = all_flavor_names
  end

  UI.header("Starting App Store download. Flavors to process: #{flavors_to_download.join(', ')}")

  # 4. Loop through each flavor and download
  flavors_to_download.each do |flavor_key|

    flavor = flavor_key

    # spec_loader.get_package_id handles the bundle_identifier
    final_api_key_path = spec_loader.get_api_key_path(platform, flavor) || params[:api_key_path]
    final_package_name = spec_loader.get_package_id(platform, flavor) || params[:package_name]

    UI.message("⬇️ Downloading store content for **#{flavor}** flavor...")

    begin
      success = annai_lanes.download_from_store(
        package_name: final_package_name,
        api_key_path: final_api_key_path,
        flavor: flavor,
        platform: platform.to_s,
        use_live_version: params[:use_live_version],
        metadata_path: params[:metadata_path],
        screenshots_path: params[:screenshots_path],
        distribution_platform: params[:distribution_platform],
      )

      if success
        UI.success("✅ Successfully downloaded app store content for flavor: #{flavor}")
      else
        # If download_from_store returns false (meaning it caught an error and logged it), flag the overall failure.
        # We only raise/log here if the inner action didn't handle it, to ensure logging consistency.
        if !status_manager.instance_variable_get(:@status).key?([flavor, "download_from_store", platform.to_s])
          raise "Download failed for flavor '#{flavor}'"
        else
          raise "Download failed for flavor '#{flavor}' (error logged previously)"
        end
      end

    rescue => e
      # Failure handling: Log the error and continue
      status_manager.logError(flavor, action_name, platform, e.message) unless status_manager.instance_variable_get(:@status).key?([flavor, "download_from_store", platform.to_s])

      UI.error("❌ Failed to download content for flavor: #{flavor}. Continuing to next flavor...")
      any_download_failed = true
      # Continue to the next flavor
    end
  end

  # 5. Final Reporting and Status Check
  annai_lanes.finalize

  if any_download_failed
      UI.user_error!("Download failed for one or more flavors. See the Annai Fastlane summary above")
  else
      UI.success("🎉 Successfully downloaded App Store content for all #{flavors_to_download.count} requested flavor(s)!")
  end
end