ann-flavor-flutter 0.1.13 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16d7f58e4027292d95f6a258d4ff3c3ac7b26b76c6cfc60c9406af289fa97fdc
4
- data.tar.gz: 4027de193deef4a6293fef30bf505fe57412f82255dcc7d036b62c6de28d55d3
3
+ metadata.gz: cb2b8ab1ad12ea68a12a8a93b557f7c614bc7f219dc48137353d2057f3ecb9d8
4
+ data.tar.gz: 2b82e97deb90ac3b49f6f158553f23e6e701b1f66d59138e3f4a57ccb0e3745c
5
5
  SHA512:
6
- metadata.gz: 19f6a97ecde33b1d933bf4ae0e4a0e7016214a04c0f52c9d5940cc0625a04637ad65b0fd87fdf1be848843e20b23bbb110135c41a33b99fb59a04ac07199c26e
7
- data.tar.gz: 1972bfc4ba0b631a6551214620d5f94afff4e2d2871ee4229cc9024e60216ec57ce2475e316bc312f733cef12853a54fc4d1fa4b26d71cc39b0f5bf6586fd368
6
+ metadata.gz: af65440fa998b255208fa86d8111ac53cedfb3fc137d99c91e8ce9939745c6a03cadfadd6b7dd5b1038bf05c80fc5e5b8e7f9119fa736fb4d7fb14f8a212e6f1
7
+ data.tar.gz: e3023ec10784fbeaa677aa1a141ae03f4779ca29c8ff307f0dc8199aac703f14c8a48df8852c363adb7a7c0b883e73e809952bf220eb1acf5e1cdb7741847a28
data/CHANGELOG.md ADDED
@@ -0,0 +1,90 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0
4
+
5
+ **Hard error on removed fields** — `firebase_app_id` and `build_target` inside any
6
+ iOS `firebase` block in `annspec.yaml` are now hard errors. The plugin raises
7
+ `UI.user_error!` and halts immediately at lane start. Remove both fields from your spec:
8
+
9
+ - `GOOGLE_APP_ID` is now read automatically from the generated
10
+ `lib/generated/firebase/{flavor}_{build_type}_ios_firebase_options.dart` file
11
+ (produced by `dart run ann_flutter_flavor sync`).
12
+ - Xcode build target is derived automatically as `{BuildType}-{flavorKey}`
13
+ (e.g. `Release-ledger_in`).
14
+
15
+ **`ANN_GOOGLE_APP_ID` env var fallback** — when the generated firebase options dart
16
+ file is missing (e.g. a fresh CI environment before sync has been run), `GOOGLE_APP_ID`
17
+ falls back to the `ANN_GOOGLE_APP_ID` environment variable. A `UI.important` warning
18
+ is printed to guide you to run sync and remove the dependency.
19
+
20
+ ## 0.1.14
21
+
22
+ Internal publish-workflow improvements. No user-facing changes.
23
+
24
+ ## 0.1.13
25
+
26
+ **`enabled: false` support** — if `annspec.yaml` sets `enabled: false`, all lanes
27
+ skip execution silently. Previously the plugin would error on a disabled spec.
28
+
29
+ **Improved error messages** — field validation errors now include the exact YAML path
30
+ and a fix hint.
31
+
32
+ ## 0.1.12
33
+
34
+ **Breaking: `annai_app:` root key renamed to `app:`** — `annspec.yaml` files using
35
+ the old `annai_app:` root key must be updated.
36
+
37
+ ## 0.1.11
38
+
39
+ Internal version bump. No user-facing changes.
40
+
41
+ ## 0.1.10
42
+
43
+ Internal version bump. No user-facing changes.
44
+
45
+ ## 0.1.9
46
+
47
+ **Firebase `service_account` support** — `firebase_token_file` is replaced by
48
+ `service_account`. The resolved path is exported as `GOOGLE_APPLICATION_CREDENTIALS`
49
+ before invoking Firebase CLI commands.
50
+
51
+ **Schema restructure** — `android.sdk` moved under `android.default.sdk`;
52
+ credentials fields reorganised under `credentials.signing`. Existing specs must be
53
+ updated to the new structure.
54
+
55
+ ## 0.1.8
56
+
57
+ Documentation and sync-workflow updates. No user-facing behaviour changes.
58
+
59
+ ## 0.1.7
60
+
61
+ **Plugin internals renamed** — internal Ruby module renamed from `ann_flutter_flavor`
62
+ to `ann_flavor_flutter` to match the gem name convention. No API change.
63
+
64
+ ## 0.1.6
65
+
66
+ **Firebase config refactored** — `path`, `firebase_app_id`, and `build_target` are
67
+ replaced by `config_file` and `project_id`. The plugin now reads `config_file` to
68
+ locate the Google services JSON instead of using the old fields.
69
+
70
+ ## 0.1.5
71
+
72
+ **`admob.gms_ads_id` cascade fixed** — `get_gms_ads_id` now correctly reads from
73
+ `admob.gms_ads_id` at every cascade level (was silently returning nil for iOS default
74
+ cascade).
75
+
76
+ **Store fields added** — `samsung_galaxy` and `amazon` store IDs are now parsed and
77
+ accessible via `YamlSpecLoader`.
78
+
79
+ ## 0.1.4
80
+
81
+ **`integrations.fastlane` gate** — the plugin checks `integrations.fastlane: true`
82
+ before running. Specs without this flag skip all Fastlane execution.
83
+
84
+ ## 0.1.3
85
+
86
+ Internal publish pipeline improvements. No user-facing behaviour changes.
87
+
88
+ ## 0.1.2
89
+
90
+ Initial release.
@@ -1,3 +1,3 @@
1
1
  module AnnFlavorFlutter
2
- VERSION = "0.1.13"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -94,7 +94,6 @@ module Fastlane
94
94
  skip_compile: params[:skip_compile],
95
95
  skip_sound_null_safety: params[:skip_sound_null_safety],
96
96
  firebase_project: params[:firebase_project],
97
- firebase_token: params[:firebase_token] || ENV["FIREBASE_TOKEN"],
98
97
  )
99
98
 
100
99
  if success
@@ -151,11 +150,6 @@ module Fastlane
151
150
  default_value: false),
152
151
 
153
152
  # --- Web / Firebase Specific Parameters ---
154
- FastlaneCore::ConfigItem.new(key: :firebase_token,
155
- description: "Firebase CLI CI token for authentication (generated via 'firebase login:ci')",
156
- optional: true,
157
- env_name: "FIREBASE_TOKEN",
158
- type: String),
159
153
  FastlaneCore::ConfigItem.new(key: :firebase_project,
160
154
  description: "The Firebase Project ID to deploy to. This value overrides the 'project_id' in the annai spec file",
161
155
  optional: true,
@@ -162,7 +162,7 @@ module FastlaneFlutterFlavor
162
162
  # New method to compile web build and deploy to Firebase Hosting
163
163
  def upload_to_firebase(flavor: "", main_file: "lib/main.dart", build_config: "release",
164
164
  skip_compile: false, skip_sound_null_safety: false,
165
- firebase_project:, firebase_token:) # firebase_project is the user override
165
+ firebase_project:)
166
166
 
167
167
  begin
168
168
  unless @isWeb
@@ -216,12 +216,14 @@ module FastlaneFlutterFlavor
216
216
  # 5. Write the updated firebase.json back to disk
217
217
  File.write(firebase_config_path, JSON.pretty_generate(config))
218
218
 
219
- token = firebase_token.to_s.strip
220
- if token.empty?
221
- token = @specLoader.get_firebase_token_from_properties.to_s.strip
222
- unless token.empty?
223
- Fastlane::UI.message("Successfully retrieved Firebase token from external properties file.")
224
- end
219
+ # Resolve service account for ADC auth — set GOOGLE_APPLICATION_CREDENTIALS if found
220
+ sa_path = @specLoader.get_service_account(@platform, flavor, build_config)
221
+ env_overrides = {}
222
+ if sa_path && File.exist?(sa_path)
223
+ env_overrides['GOOGLE_APPLICATION_CREDENTIALS'] = sa_path
224
+ Fastlane::UI.message("Using service account for Firebase auth: #{sa_path}")
225
+ elsif sa_path
226
+ Fastlane::UI.error("service_account file not found at: #{sa_path}")
225
227
  end
226
228
 
227
229
  # 6. Deploy to Firebase Hosting using the determined ID
@@ -230,17 +232,15 @@ module FastlaneFlutterFlavor
230
232
  "--only", "hosting",
231
233
  "--project", final_project_id,
232
234
  ]
233
- # Only add the token flags if token is present
234
- if !token.empty?
235
- command_parts.push("--token", token)
236
- end
237
235
 
238
236
  firebase_root = @root_folder
239
237
 
240
238
  Fastlane::UI.message("Executing Firebase deploy command: #{command_parts.join(' ')}")
241
239
 
242
240
  Dir.chdir firebase_root do
241
+ env_overrides.each { |k, v| ENV[k] = v }
243
242
  Fastlane::Actions::sh(*command_parts)
243
+ env_overrides.keys.each { |k| ENV.delete(k) }
244
244
  end
245
245
 
246
246
  @statusManager.logSuccess flavor, "upload_to_firebase", @platform
@@ -32,7 +32,7 @@ module FastlaneFlutterFlavor
32
32
  end
33
33
 
34
34
  loader = YamlSpecLoader.new(root, spec_file)
35
- self.new(loader, flavor, config_name)
35
+ self.new(loader, flavor, root, config_name)
36
36
  end
37
37
 
38
38
  # Injects YAML values into the Xcode Project Build Settings
@@ -87,9 +87,10 @@ module FastlaneFlutterFlavor
87
87
  puts "[Annai] Successfully injected flavor '#{log_flavor}' settings into Xcode configurations."
88
88
  end
89
89
 
90
- def initialize(loader, flavor, config_name = nil)
90
+ def initialize(loader, flavor, project_root, config_name = nil)
91
91
  @loader = loader
92
92
  @flavor = flavor
93
+ @project_root = project_root
93
94
  @platform = :ios
94
95
 
95
96
  # BUILD TYPE DETECTION: Prioritize Flutter CLI mode, fallback to config name regex
@@ -145,9 +146,32 @@ module FastlaneFlutterFlavor
145
146
  end
146
147
 
147
148
  def google_app_id
148
- # Manual lookup for nested Firebase IDs (using build_type for debug/release)
149
- config = @loader.get_merged_flavor_config(@platform, @flavor)
150
- config.dig('firebase', @build_type, 'firebase_app_id') || ''
149
+ # Primary: read appId from the generated firebase_options dart file.
150
+ # File is generated by `dart run ann_flutter_flavor sync` and committed to the repo.
151
+ dart_file = File.join(
152
+ @project_root,
153
+ "lib/generated/firebase/#{@flavor}_#{@build_type}_ios_firebase_options.dart"
154
+ )
155
+ if File.exist?(dart_file)
156
+ content = File.read(dart_file)
157
+ match = content.match(/appId:\s*'([^']+)'/) ||
158
+ content.match(/appId:\s*"([^"]+)"/)
159
+ return match[1] if match
160
+ end
161
+
162
+ # Fallback: ANN_GOOGLE_APP_ID env var — use when the dart file is missing
163
+ # (e.g. fresh CI environment before sync has been run).
164
+ env_value = ENV['ANN_GOOGLE_APP_ID']
165
+ if env_value && !env_value.empty?
166
+ Fastlane::UI.important(
167
+ "[Annai] GOOGLE_APP_ID read from ANN_GOOGLE_APP_ID env var for " \
168
+ "#{@flavor}/#{@build_type}. Run 'dart run ann_flutter_flavor sync' " \
169
+ "to generate the source file and remove this dependency."
170
+ )
171
+ return env_value
172
+ end
173
+
174
+ ''
151
175
  end
152
176
  end
153
177
  end
@@ -30,7 +30,12 @@ module FastlaneFlutterFlavor
30
30
  unless yaml_content.is_a?(Hash)
31
31
  raise "YAML content must be a top-level Hash."
32
32
  end
33
+
34
+ check_removed_firebase_fields(yaml_content)
35
+
33
36
  return yaml_content
37
+ rescue Fastlane::Shell::ShellError => e
38
+ raise e
34
39
  rescue => e
35
40
  # Use @file_path for reporting the error path
36
41
  Fastlane::UI.error("Failed to load or parse annai spec YAML file at #{@file_path}: #{e.message}")
@@ -38,6 +43,45 @@ module FastlaneFlutterFlavor
38
43
  end
39
44
  end
40
45
 
46
+ # Raises UI.user_error! if firebase_app_id or build_target are present in any iOS firebase block.
47
+ # Both fields were removed — they are derived automatically now.
48
+ def check_removed_firebase_fields(spec_data)
49
+ ios_app = spec_data.dig('app', 'ios')
50
+ return unless ios_app.is_a?(Hash)
51
+
52
+ sections = {}
53
+ sections['ios.default'] = ios_app.dig('default') || {}
54
+
55
+ flavors = ios_app.dig('flavor') || {}
56
+ flavors.each do |flavor_key, flavor_data|
57
+ sections["ios.flavor.#{flavor_key}"] = flavor_data || {}
58
+ end
59
+
60
+ sections.each do |section_path, section_data|
61
+ build_types = section_data.dig('build_types') || {}
62
+ build_types.each do |bt_key, bt_data|
63
+ next unless bt_data.is_a?(Hash)
64
+ firebase_block = bt_data.dig('firebase') || {}
65
+ next unless firebase_block.is_a?(Hash)
66
+
67
+ if firebase_block.key?('firebase_app_id')
68
+ Fastlane::UI.user_error!(
69
+ "[#{section_path}/#{bt_key}] `firebase_app_id` is no longer supported in annspec.yaml. " \
70
+ "Remove it — GOOGLE_APP_ID is now read from the generated firebase_options dart file."
71
+ )
72
+ end
73
+
74
+ if firebase_block.key?('build_target')
75
+ Fastlane::UI.user_error!(
76
+ "[#{section_path}/#{bt_key}] `build_target` is no longer supported in annspec.yaml. " \
77
+ "Remove it — the Xcode build target is derived automatically as " \
78
+ "'#{bt_key.to_s.capitalize}-#{section_path.split('.').last}'."
79
+ )
80
+ end
81
+ end
82
+ end
83
+ end
84
+
41
85
  # Recursively merges defaults into a flavor's data.
42
86
  # This function prioritizes 'current_data' (the flavor-specific value).
43
87
  # If a key is present in 'default_data' but missing in 'current_data',
@@ -279,49 +323,25 @@ module FastlaneFlutterFlavor
279
323
  config.dig('build_types', build_config, 'firebase', 'project_id') if config
280
324
  end
281
325
 
282
- # Retrieves the firebase token from a external .properties file
283
- # as defined in app -> general -> firebase_token_file
284
- # @return [String, nil] The token value, or nil if not found/error.
285
- def get_firebase_token_from_properties
326
+ # Returns the resolved service_account path for the given platform/flavor/build_config,
327
+ # cascading from flavor build_type default build_type.
328
+ # @return [String, nil]
329
+ def get_service_account(platform, flavor_name, build_config)
286
330
  return nil unless @spec_data
287
331
 
288
- # 1. Get the properties file path from the YAML spec
289
- # Path: app -> general -> firebase_token_file
290
- rel_props_path = @spec_data.dig('app', 'general', 'firebase_token_file')
291
-
292
- if rel_props_path.nil? || rel_props_path.empty?
293
- Fastlane::UI.verbose("No 'firebase_token_file' defined in app -> general.")
294
- return nil
295
- end
332
+ platform_data = @spec_data.dig('app', platform)
333
+ return nil unless platform_data
296
334
 
297
- # 2. Resolve the full path relative to project root
298
- full_props_path = File.expand_path(rel_props_path, @root_folder)
335
+ flavor_data = platform_data.dig('flavor', flavor_name) || {}
336
+ default_data = platform_data['default'] || {}
299
337
 
300
- unless File.exist?(full_props_path)
301
- Fastlane::UI.error("Firebase token file not found at: #{full_props_path}")
302
- return nil
303
- end
338
+ flavor_bt_sa = flavor_data.dig('build_types', build_config, 'firebase', 'service_account')
339
+ default_bt_sa = default_data.dig('build_types', build_config, 'firebase', 'service_account')
304
340
 
305
- # 3. Parse the .properties file for FIREBASE_TOKEN
306
- begin
307
- File.foreach(full_props_path) do |line|
308
- # Remove whitespace and skip comments/empty lines
309
- line = line.strip
310
- next if line.empty? || line.start_with?('#', '!')
311
-
312
- # Match KEY=VALUE (handles both = and : as separators)
313
- if line =~ /^\s*FIREBASE_TOKEN\s*[=:]\s*(.*)$/
314
- token = $1.strip
315
- # Remove optional surrounding quotes if present
316
- return token.gsub(/^['"]|['"]$/, '')
317
- end
318
- end
319
- rescue => e
320
- Fastlane::UI.error("Error reading properties file at #{rel_props_path}: #{e.message}")
321
- end
341
+ path = flavor_bt_sa || default_bt_sa
342
+ return nil if path.nil? || path.empty?
322
343
 
323
- Fastlane::UI.verbose("FIREBASE_TOKEN key not found in #{rel_props_path}")
324
- return nil
344
+ File.expand_path(path, @root_folder)
325
345
  end
326
346
 
327
347
  # For AdMob (annai_ads)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ann-flavor-flutter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ANN Solutions
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-06-27 00:00:00.000000000 Z
11
+ date: 2026-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fastlane
@@ -74,6 +74,7 @@ extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - ".gitignore"
77
+ - CHANGELOG.md
77
78
  - Gemfile
78
79
  - README.md
79
80
  - Rakefile