ann-flavor-flutter 0.4.6 → 0.4.8

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: 2884061122825135d9f07bb18db889d23509649848aca1fca2c45b63b9b8c3bd
4
- data.tar.gz: 5ed44c51bcf6c29195763aaa2615f4bb59b71a5b0908f26fdbc83677419273a4
3
+ metadata.gz: a70549206a408d933bf2258bf1c8b21ba4b1439d926e106a67f08564a2eac3fe
4
+ data.tar.gz: 0ff6ede39627802182e5ace0a13ab8d5a48075539f65827a52dbd9bfcc838373
5
5
  SHA512:
6
- metadata.gz: 8635f03da486e2aa4da6a7c9ed423d76260624ff5710a58c4a174951ecf2922bd874e4ff197edcb551db650ae7ef3fc76725d4f58935a076785f0c3f203e3a81
7
- data.tar.gz: 0e5a13e1e4c03ddf24b31bb7b7c07fd330934213601b7a373408fdb051b8cfb2bb0bf298a9ad254df1ede039315b4871f6b2ff44a90818c7574a7361f2f197b6
6
+ metadata.gz: d3d91d71d2a5321d94b3211cc0818430a4525ef5fb65ca8d80e9cad5c2471f111556aee73452a6265179f4569e591c2f79661024c0959ead917b94115f1a445a
7
+ data.tar.gz: 6e90f40ea8ea0736b6984c30389916cbbe395116b7efdb4defde155da342174c0c62cec528c726fd698f9f6715d6821b67020518acb1a5db58d755e4b765c729
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.8
4
+
5
+ ### Added
6
+ - `info_plist` schema field added to the shared core (`ann-flavor-core-ruby`, vendored into this plugin) — a new iOS-only field for raw `Info.plist` overrides, valid at `default`/`flavor`/`build_type` levels, as either an inline map or a file-path reference. Core-only in this release — no Fastlane lane or helper reads this field yet. Included here purely because this plugin vendors the shared core and versions travel together.
7
+
8
+ ## 0.4.7
9
+
10
+ ### Fixed
11
+ - `dart_defines` (`annspec.yaml`'s `android.default.dart_defines` / per-flavor overrides) was silently never applied to `flutter build` when compilation happened as part of `upload_to_play_store`, `upload_to_app_store`, or `upload_to_cloudflare` — only a manual `bundle exec fastlane android compile_build` invocation picked it up, since the flag was injected only into the generated Fastfile's standalone `compile_build` lane, which those upload/publish helpers never call. `compile_build` (the shared helper in `lanes_annai.rb`) now resolves `dart_defines` itself at runtime, so every caller gets it automatically — this also means a flavor-level `dart_defines` override is now honored, which the old generation-time injection could never represent (it could only see default-level values). ([#59](https://github.com/anntech-dev/ann-flavor-tooling/issues/59))
12
+
3
13
  ## 0.4.6
4
14
 
5
15
  ### Fixed
@@ -1,3 +1,3 @@
1
1
  module AnnFlavorFlutter
2
- VERSION = "0.4.6"
2
+ VERSION = "0.4.8"
3
3
  end
@@ -113,6 +113,22 @@ module FastlaneFlutterFlavor
113
113
  end
114
114
  end
115
115
 
116
+ # dart_defines (REQ-DDEF-00040): resolved here — not only in the
117
+ # standalone Fastfile `compile_build` lane — so every caller that
118
+ # compiles via this helper gets it, including upload_to_play_store,
119
+ # upload_to_app_store, and upload_to_cloudflare, which call this
120
+ # method directly and previously never applied dart_defines at all
121
+ # (DEF-059, #59). A caller-supplied additional_parameter is preserved
122
+ # and the resolved flags are appended alongside it as separate argv
123
+ # elements (Fastlane::Actions.sh below is called with a splatted
124
+ # array, so each flag must be its own element, not one combined
125
+ # string). additional_parameter may already be an Array here (the web
126
+ # branch above turns it into one) or a String.
127
+ dart_defines_flags = @specLoader.get_dart_defines_flags(@platform, flavor, build_config)
128
+ unless dart_defines_flags.empty?
129
+ additional_parameter = Array(additional_parameter).flatten.reject { |p| p.to_s.empty? } + dart_defines_flags
130
+ end
131
+
116
132
  # Base command parts
117
133
  command_parts = [
118
134
  "flutter", "build",
@@ -329,5 +329,27 @@ module FastlaneFlutterFlavor
329
329
  resolved = resolve(platform, flavor_name, build_config)
330
330
  resolved&.effective_auth&.reversed_client_id
331
331
  end
332
+
333
+ # Merges common + compile-scoped dart_defines (compile wins on collision,
334
+ # per REQ-DDEF-00015) into individual --dart-define=KEY=VALUE flags for
335
+ # `flutter build`. Returns [] when there's nothing to emit. Returned as
336
+ # separate array elements (not a single joined string) so callers can pass
337
+ # them straight through to Fastlane::Actions.sh's argv-array form without
338
+ # each flag being treated as one combined shell argument.
339
+ #
340
+ # REQ-DDEF-00040's default-only scoping decision applies here too:
341
+ # `resolve` folds flavor-level overrides in via the core's 4-level cascade,
342
+ # so a flavor with its own dart_defines still resolves correctly per call —
343
+ # unlike the (now-removed) generated-Fastfile-lane version, which could
344
+ # only represent default-level dart_defines since it was a single static
345
+ # lane shared across every flavor.
346
+ def get_dart_defines_flags(platform, flavor_name, build_type = 'release')
347
+ resolved = resolve(platform, flavor_name, build_type)
348
+ defines = resolved&.effective_dart_defines
349
+ return [] unless defines
350
+
351
+ merged = (defines.common || {}).merge(defines.compile || {})
352
+ merged.map { |k, v| "--dart-define=#{k}=#{v}" }
353
+ end
332
354
  end
333
355
  end
@@ -65,7 +65,7 @@ module AnnFlavorCore
65
65
 
66
66
  IosDefault = Struct.new(
67
67
  :id, :name, :version_name, :version_code, :main_file,
68
- :admob, :icon, :credentials, :firebase, :build_types, :custom, :dart_defines,
68
+ :admob, :icon, :credentials, :firebase, :build_types, :custom, :dart_defines, :info_plist,
69
69
  keyword_init: true
70
70
  ) do
71
71
  def self.defaults = new(build_types: {}, custom: {}, dart_defines: DartDefines.defaults)
@@ -73,7 +73,7 @@ module AnnFlavorCore
73
73
 
74
74
  IosFlavor = Struct.new(
75
75
  :id, :id_suffix, :name, :name_suffix, :version_name, :version_code,
76
- :main_file, :admob, :icon, :firebase, :stores, :credentials, :build_types, :custom, :dart_defines,
76
+ :main_file, :admob, :icon, :firebase, :stores, :credentials, :build_types, :custom, :dart_defines, :info_plist,
77
77
  keyword_init: true
78
78
  ) do
79
79
  def self.defaults = new(id_suffix: '', name_suffix: '', build_types: {}, custom: {}, dart_defines: DartDefines.defaults)
@@ -139,7 +139,7 @@ module AnnFlavorCore
139
139
  :id_suffix, :name_suffix,
140
140
  :firebase, :auth, :admob,
141
141
  :minify_enabled, :shrink_resources, :lint_check_release_builds,
142
- :ndk_version, :ndk_debug_symbol_level, :ndk_abi_filters, :custom, :dart_defines,
142
+ :ndk_version, :ndk_debug_symbol_level, :ndk_abi_filters, :custom, :dart_defines, :info_plist,
143
143
  keyword_init: true
144
144
  ) do
145
145
  def self.defaults = new(id_suffix: '', name_suffix: '', ndk_abi_filters: [], custom: {}, dart_defines: DartDefines.defaults)
@@ -191,6 +191,7 @@ module AnnFlavorCore
191
191
  :effective_cloudflare,
192
192
  :effective_custom,
193
193
  :effective_dart_defines,
194
+ :effective_info_plist,
194
195
  keyword_init: true
195
196
  )
196
197
  end
@@ -162,6 +162,7 @@ module AnnFlavorCore
162
162
  build_types: parse_build_type_configs(h(m, 'build_types')),
163
163
  custom: parse_custom_config(h(m, 'custom')),
164
164
  dart_defines: parse_dart_defines(h(m, 'dart_defines')),
165
+ info_plist: m['info_plist'],
165
166
  )
166
167
  end
167
168
 
@@ -182,6 +183,7 @@ module AnnFlavorCore
182
183
  build_types: parse_build_type_configs(h(m, 'build_types')),
183
184
  custom: parse_custom_config(h(m, 'custom')),
184
185
  dart_defines: parse_dart_defines(h(m, 'dart_defines')),
186
+ info_plist: m['info_plist'],
185
187
  )
186
188
  end
187
189
 
@@ -313,6 +315,7 @@ module AnnFlavorCore
313
315
  ndk_abi_filters: (v['ndkAbiFilters'].is_a?(Array) ? v['ndkAbiFilters'] : []),
314
316
  custom: parse_custom_config(h(v, 'custom')),
315
317
  dart_defines: parse_dart_defines(h(v, 'dart_defines')),
318
+ info_plist: v['info_plist'],
316
319
  )
317
320
  end
318
321
  end
@@ -111,6 +111,14 @@ module AnnFlavorCore
111
111
  effective_icon: flavor.icon || defaults.icon,
112
112
  effective_custom: resolve_custom(defaults.custom, defaults.build_types[build_type]&.custom, flavor.custom, flavor.build_types[build_type]&.custom),
113
113
  effective_dart_defines: resolve_dart_defines(defaults.dart_defines, defaults.build_types[build_type]&.dart_defines, flavor.dart_defines, flavor.build_types[build_type]&.dart_defines),
114
+ # Whole-value most-specific-wins — unlike firebase's per-field merge,
115
+ # info_plist's value (an arbitrary Hash, or a file-path String) has no
116
+ # fixed sub-fields to merge independently, so a more specific level's
117
+ # value replaces a less specific one entirely rather than being merged
118
+ # key-by-key here (per-key content merging across levels happens later,
119
+ # in the consuming plugin, not in the core).
120
+ effective_info_plist: flavor.build_types[build_type]&.info_plist || flavor.info_plist ||
121
+ defaults.build_types[build_type]&.info_plist || defaults.info_plist,
114
122
  )
115
123
  end
116
124
 
@@ -20,7 +20,13 @@ module AnnFlavorCore
20
20
  module StrictModeChecker
21
21
  # Fields whose value is a free-form Hash (arbitrary user-declared keys are data,
22
22
  # not schema) -- exempted from unknown-key checking entirely, at any level.
23
- FREE_FORM_FIELDS = %i[custom dart_defines].freeze
23
+ #
24
+ # info_plist is additionally a union (an inline Hash OR a plain file-path String),
25
+ # so even when its value IS a Hash, its keys are raw Info.plist keys the user
26
+ # controls, never our own schema fields -- same free-form treatment as
27
+ # custom/dart_defines, and deliberately NOT in RECURSION_TARGETS since there is
28
+ # no single fixed struct type to recurse into.
29
+ FREE_FORM_FIELDS = %i[custom dart_defines info_plist].freeze
24
30
 
25
31
  # (containing_struct, field_name) => target_struct — only the "does this field
26
32
  # recurse, and into what" relationship; the valid-keys-within-that-struct question
@@ -28,6 +34,7 @@ module AnnFlavorCore
28
34
  RECURSION_TARGETS = {
29
35
  [AnnSpec, :app] => AnnApp,
30
36
  [AnnSpec, :tooling] => ToolingConfig,
37
+ [AnnSpec, :debug_config] => DebugConfig, # via `debug:` YAML key
31
38
  [AnnApp, :android] => AndroidPlatform,
32
39
  [AnnApp, :ios] => IosPlatform,
33
40
  [AnnApp, :web] => WebPlatform,
@@ -93,6 +100,40 @@ module AnnFlavorCore
93
100
  # user-chosen name (flavor name, build-type name), not a single nested Hash.
94
101
  MAP_VALUED_FIELDS = %i[flavors build_types].freeze
95
102
 
103
+ # Deliberate Struct-member <-> YAML-key naming exceptions in the schema -- keys
104
+ # where the YAML key is NOT simply the snake_case member name, so a fixed,
105
+ # explicit override is required rather than a growing hand-maintained registry:
106
+ #
107
+ # - `flavors` (Struct member) reads YAML key `flavor` (singular).
108
+ # - Every other entry below is parsed from a literal camelCase YAML key by
109
+ # AnnFlavorCore::Parser (unlike the rest of the schema, which is
110
+ # snake_case) -- this list was derived by exhaustively scanning every
111
+ # string-literal map key the parser reads, not by manual inspection,
112
+ # after two rounds of under-scoped fixes (ndk_abi_filters, then
113
+ # client_id) missed entries this way. Matches the Dart core's
114
+ # hand-written registry and the Kotlin core's equivalent override map,
115
+ # both of which already have all of these correct.
116
+ FIELD_TO_YAML_KEY = {
117
+ flavors: 'flavor',
118
+ debug_config: 'debug',
119
+ client_id: 'clientId',
120
+ compile_sdk: 'compileSdk',
121
+ lint_check_release_builds: 'lintCheckReleaseBuilds',
122
+ min_sdk: 'minSdk',
123
+ minify_enabled: 'minifyEnabled',
124
+ ndk_abi_filters: 'ndkAbiFilters',
125
+ ndk_debug_symbol_level: 'ndkDebugSymbolLevel',
126
+ ndk_version: 'ndkVersion',
127
+ print_build_and_flavor_info: 'printBuildAndFlavorInfo',
128
+ print_debug: 'printDebug',
129
+ print_release_build_type_info: 'printReleaseBuildTypeInfo',
130
+ print_sdk_versions: 'printSdkVersions',
131
+ reversed_client_id: 'reversedClientId',
132
+ shrink_resources: 'shrinkResources',
133
+ target_sdk: 'targetSdk',
134
+ }.freeze
135
+ YAML_KEY_TO_FIELD = FIELD_TO_YAML_KEY.each_with_object({}) { |(f, y), h| h[y] = f }.freeze
136
+
96
137
  def self.check(raw, root_struct)
97
138
  issues = []
98
139
  walk(raw, root_struct, '', issues)
@@ -102,10 +143,7 @@ module AnnFlavorCore
102
143
  def self.walk(raw, struct_class, path, issues)
103
144
  return unless raw.is_a?(Hash)
104
145
 
105
- valid_keys = struct_class.members.map(&:to_s)
106
- # `flavors` (Struct member) reads YAML key `flavor` (singular) -- the one
107
- # deliberate field-name <-> YAML-key exception in the schema.
108
- valid_keys = valid_keys.map { |k| k == 'flavors' ? 'flavor' : k }
146
+ valid_keys = struct_class.members.map { |m| FIELD_TO_YAML_KEY[m] || m.to_s }
109
147
 
110
148
  raw.each do |raw_key, raw_value|
111
149
  key = raw_key.to_s
@@ -117,7 +155,7 @@ module AnnFlavorCore
117
155
  next
118
156
  end
119
157
 
120
- field_sym = (key == 'flavor' ? 'flavors' : key).to_sym
158
+ field_sym = YAML_KEY_TO_FIELD[key] || key.to_sym
121
159
  next if FREE_FORM_FIELDS.include?(field_sym)
122
160
 
123
161
  target_struct = RECURSION_TARGETS[[struct_class, field_sym]]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ann-flavor-flutter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.6
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - ANN Solutions