ann-flavor-flutter 0.2.2 → 0.4.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 +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/ann_flavor_flutter/version.rb +1 -1
- data/lib/fastlane/plugin/ann_flavor_flutter/actions/ann_upload_to_cloudflare_action.rb +166 -0
- data/lib/fastlane/plugin/ann_flavor_flutter/helper/lanes_annai.rb +87 -1
- data/lib/fastlane/plugin/ann_flavor_flutter/helper/utils_spec_loader.rb +22 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c130b0210def1ac340db96f188146dbef72a1550d914b77fa062cd25f7ccb279
|
|
4
|
+
data.tar.gz: 4688888ece3b6fa767225b16d644da23ea7f2762eb6a2b92c95742d309adcb09
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8940badbe14a1fb8de04d6af4dcf58bba368c329d30434889b1d400703f5f9e1a5dfb6da075c7c677547bc35d699d4c0c775a51519aa72bded1a7a2b445d09db
|
|
7
|
+
data.tar.gz: 30052ccd783ff8f93533467423c3173f50799fd979e385ca56c599aaab8de67713a6eb11971d79c8d28c2e532fc2c93e0e779e1060d2e1a6e2689c0bcec5dc0d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Plan 027**: New `ann_upload_to_cloudflare` action — deploys web flavors to Cloudflare Pages (`wrangler pages deploy`) or Cloudflare Workers (`wrangler deploy --config`). Reads `cloudflare.{project_name, account_id, branch, mode}` from `annspec.yaml` with cascade: flavor → default → fallback (`main`, `pages`). `project_name` is flavor-only (never inherited from default). `account_id` falls back to `CLOUDFLARE_ACCOUNT_ID` env var.
|
|
7
|
+
- `lanes_annai.rb` gains `upload_to_cloudflare` method and `web_output_dir` private helper.
|
|
8
|
+
- `flutter build web` now appends `--output=build/web/<flavor>` when a flavor is specified, matching the output directory used by both Firebase and Cloudflare deploy steps.
|
|
9
|
+
- `upload_to_firebase` uses `web_output_dir(flavor)` for the `public` dir in `firebase.json` so it matches the per-flavor build output.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 0.3.0
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **Plan 026**: `@isWeb` branch in `lanes_annai.rb` now calls `dart run ann_flutter_flavor sync-web --flavor <name>` before `flutter build web`. Zero Ruby copy logic — preprocessing fully delegated to the Flutter CLI.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
3
20
|
## 0.2.1
|
|
4
21
|
|
|
5
22
|
### Added
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
require 'fastlane/action'
|
|
2
|
+
require 'fastlane/plugin/ann_flavor_flutter/helper/lanes_annai'
|
|
3
|
+
require 'fastlane/plugin/ann_flavor_flutter/helper/utils_spec_loader'
|
|
4
|
+
|
|
5
|
+
module Fastlane
|
|
6
|
+
module Actions
|
|
7
|
+
class AnnaiUploadToCloudflareAction < Action
|
|
8
|
+
|
|
9
|
+
def self.run(params)
|
|
10
|
+
platform = :web
|
|
11
|
+
spec_file = params[:spec_file]
|
|
12
|
+
|
|
13
|
+
annai_lanes = FastlaneFlutterFlavor::AnnaiLanes.new(
|
|
14
|
+
lane: self,
|
|
15
|
+
platform: platform,
|
|
16
|
+
spec_file: spec_file
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
status_manager = annai_lanes.instance_variable_get(:@statusManager)
|
|
20
|
+
spec_loader = annai_lanes.instance_variable_get(:@specLoader)
|
|
21
|
+
UI.user_error!("Internal Error: AnnaiLanes failed to initialize specLoader") unless spec_loader
|
|
22
|
+
|
|
23
|
+
if params[:clean]
|
|
24
|
+
UI.header("🧹 Cleaning builds as requested...")
|
|
25
|
+
begin
|
|
26
|
+
annai_lanes.clean_build
|
|
27
|
+
rescue => e
|
|
28
|
+
UI.error("Failed to perform clean build: #{e.message}")
|
|
29
|
+
status_manager.logError("All", "annai_clean_build", platform, e.message)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
flavors_hash = spec_loader.get_platform_flavors(platform)
|
|
34
|
+
|
|
35
|
+
if flavors_hash.empty?
|
|
36
|
+
UI.important("No flavors found for Web in the Annai spec. Nothing to deploy")
|
|
37
|
+
annai_lanes.finalize
|
|
38
|
+
return
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
all_flavor_names = flavors_hash.keys
|
|
42
|
+
|
|
43
|
+
requested_flavor = params[:flavor]
|
|
44
|
+
if requested_flavor && !requested_flavor.to_s.empty?
|
|
45
|
+
requested_flavors = requested_flavor.to_s.split(',').map(&:strip).reject(&:empty?)
|
|
46
|
+
invalid = requested_flavors.reject { |f| all_flavor_names.include?(f) }
|
|
47
|
+
if invalid.any?
|
|
48
|
+
UI.user_error!("Unknown flavor(s): #{invalid.join(', ')}. Available: #{all_flavor_names.join(', ')}")
|
|
49
|
+
end
|
|
50
|
+
flavors_to_deploy = requested_flavors
|
|
51
|
+
else
|
|
52
|
+
flavors_to_deploy = all_flavor_names
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
UI.header("Deploying to Cloudflare. Flavors: #{flavors_to_deploy.join(', ')}")
|
|
56
|
+
|
|
57
|
+
any_failed = false
|
|
58
|
+
|
|
59
|
+
flavors_to_deploy.each do |flavor_key|
|
|
60
|
+
flavor = flavor_key.to_s
|
|
61
|
+
final_main_file = spec_loader.get_main_file(platform, flavor) || params[:main_file]
|
|
62
|
+
|
|
63
|
+
UI.message("🚀 Deploying flavor: #{flavor}")
|
|
64
|
+
|
|
65
|
+
begin
|
|
66
|
+
success = annai_lanes.upload_to_cloudflare(
|
|
67
|
+
flavor: flavor,
|
|
68
|
+
main_file: final_main_file,
|
|
69
|
+
build_config: params[:build_config],
|
|
70
|
+
skip_compile: params[:skip_compile],
|
|
71
|
+
skip_sound_null_safety: params[:skip_sound_null_safety],
|
|
72
|
+
project_name: params[:project_name],
|
|
73
|
+
account_id: params[:account_id],
|
|
74
|
+
branch: params[:branch],
|
|
75
|
+
mode: params[:mode],
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if success
|
|
79
|
+
UI.success("✅ Deployed #{flavor} to Cloudflare")
|
|
80
|
+
else
|
|
81
|
+
any_failed = true
|
|
82
|
+
UI.error("❌ Failed to deploy #{flavor}")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
rescue => e
|
|
86
|
+
status_manager.logError(flavor, "upload_to_cloudflare", platform, e.message)
|
|
87
|
+
UI.error("❌ #{flavor}: #{e.message}")
|
|
88
|
+
any_failed = true
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
annai_lanes.finalize
|
|
93
|
+
|
|
94
|
+
if any_failed
|
|
95
|
+
UI.user_error!("Cloudflare deployment failed for one or more flavors")
|
|
96
|
+
else
|
|
97
|
+
UI.success("🎉 Successfully deployed #{flavors_to_deploy.count} flavor(s) to Cloudflare!")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.available_options
|
|
102
|
+
[
|
|
103
|
+
FastlaneCore::ConfigItem.new(key: :flavor,
|
|
104
|
+
description: "Flavor(s) to deploy (comma-separated). Defaults to all Web flavors",
|
|
105
|
+
optional: true,
|
|
106
|
+
default_value: nil),
|
|
107
|
+
FastlaneCore::ConfigItem.new(key: :spec_file,
|
|
108
|
+
description: "Path to annspec.yaml (relative to Flutter root). Defaults to standard discovery",
|
|
109
|
+
optional: true,
|
|
110
|
+
default_value: nil),
|
|
111
|
+
FastlaneCore::ConfigItem.new(key: :clean,
|
|
112
|
+
description: "Run clean build before deploying",
|
|
113
|
+
type: Boolean,
|
|
114
|
+
default_value: false),
|
|
115
|
+
FastlaneCore::ConfigItem.new(key: :main_file,
|
|
116
|
+
description: "Path to the main Dart file",
|
|
117
|
+
default_value: "lib/main.dart"),
|
|
118
|
+
FastlaneCore::ConfigItem.new(key: :build_config,
|
|
119
|
+
description: "Flutter build configuration ('release', 'profile', 'debug')",
|
|
120
|
+
optional: true,
|
|
121
|
+
default_value: "release"),
|
|
122
|
+
FastlaneCore::ConfigItem.new(key: :skip_compile,
|
|
123
|
+
description: "Skip compilation step",
|
|
124
|
+
type: Boolean,
|
|
125
|
+
default_value: false),
|
|
126
|
+
FastlaneCore::ConfigItem.new(key: :skip_sound_null_safety,
|
|
127
|
+
description: "Skip sound null safety during compilation",
|
|
128
|
+
type: Boolean,
|
|
129
|
+
default_value: false),
|
|
130
|
+
FastlaneCore::ConfigItem.new(key: :project_name,
|
|
131
|
+
description: "Cloudflare Pages project name (overrides annspec.yaml)",
|
|
132
|
+
optional: true,
|
|
133
|
+
type: String),
|
|
134
|
+
FastlaneCore::ConfigItem.new(key: :account_id,
|
|
135
|
+
description: "Cloudflare account ID (overrides annspec.yaml and CLOUDFLARE_ACCOUNT_ID env var)",
|
|
136
|
+
optional: true,
|
|
137
|
+
type: String),
|
|
138
|
+
FastlaneCore::ConfigItem.new(key: :branch,
|
|
139
|
+
description: "Cloudflare Pages branch (overrides annspec.yaml, default: 'main')",
|
|
140
|
+
optional: true,
|
|
141
|
+
type: String),
|
|
142
|
+
FastlaneCore::ConfigItem.new(key: :mode,
|
|
143
|
+
description: "Deployment mode: 'pages' or 'workers' (overrides annspec.yaml, default: 'pages')",
|
|
144
|
+
optional: true,
|
|
145
|
+
type: String),
|
|
146
|
+
].compact
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def self.description
|
|
150
|
+
"Deploy one or all Web flavors to Cloudflare Pages or Cloudflare Workers"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.is_supported?(platform)
|
|
154
|
+
platform == :web
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def self.example_code
|
|
158
|
+
'ann_upload_to_cloudflare(
|
|
159
|
+
flavor: "ledger_in,ledger_us",
|
|
160
|
+
build_config: "release",
|
|
161
|
+
skip_compile: false
|
|
162
|
+
)'
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -105,6 +105,13 @@ module FastlaneFlutterFlavor
|
|
|
105
105
|
Fastlane::UI.message("Web compilation detected. Omitting '--flavor' from Flutter build command, but using '#{flavor}' for logging.")
|
|
106
106
|
cli_flavor = ""
|
|
107
107
|
cli_flavor_option = ""
|
|
108
|
+
# Preprocess: copy per-flavor web assets into web/ before building
|
|
109
|
+
sh("dart run ann_flutter_flavor sync-web --flavor #{flavor} --project #{@spec_root_folder}")
|
|
110
|
+
# Append per-flavor output directory when a flavor is specified
|
|
111
|
+
unless flavor.empty?
|
|
112
|
+
output_flag = "--output=#{web_output_dir(flavor)}"
|
|
113
|
+
additional_parameter = additional_parameter.to_s.empty? ? output_flag : "#{additional_parameter} #{output_flag}"
|
|
114
|
+
end
|
|
108
115
|
end
|
|
109
116
|
|
|
110
117
|
# Base command parts
|
|
@@ -208,7 +215,7 @@ module FastlaneFlutterFlavor
|
|
|
208
215
|
|
|
209
216
|
# 4. Update the hosting block
|
|
210
217
|
config['hosting'] = {
|
|
211
|
-
"public" =>
|
|
218
|
+
"public" => web_output_dir(flavor),
|
|
212
219
|
"ignore" => ["firebase.json", "**/.*", "**/node_modules/**"],
|
|
213
220
|
"rewrites" => [{"source" => "**", "destination" => "/index.html"}]
|
|
214
221
|
}
|
|
@@ -498,5 +505,84 @@ module FastlaneFlutterFlavor
|
|
|
498
505
|
@setup_lanes.cleanup
|
|
499
506
|
end
|
|
500
507
|
|
|
508
|
+
# Deploys a Flutter web build to Cloudflare Pages or Cloudflare Workers.
|
|
509
|
+
# Cascades: project_name (flavor-only), account_id/branch/mode (flavor → default → fallback).
|
|
510
|
+
def upload_to_cloudflare(flavor: "", main_file: "lib/main.dart", build_config: "release",
|
|
511
|
+
skip_compile: false, skip_sound_null_safety: false,
|
|
512
|
+
project_name: nil, account_id: nil, branch: nil, mode: nil)
|
|
513
|
+
begin
|
|
514
|
+
unless @isWeb
|
|
515
|
+
raise "upload_to_cloudflare is only supported for the :web platform (flavor: #{flavor})"
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
cf = @specLoader.get_cloudflare_config(@platform, flavor)
|
|
519
|
+
|
|
520
|
+
resolved_project_name = project_name || cf['project_name']
|
|
521
|
+
resolved_account_id = account_id || cf['account_id']
|
|
522
|
+
resolved_branch = branch || cf['branch']
|
|
523
|
+
resolved_mode = mode || cf['mode']
|
|
524
|
+
|
|
525
|
+
if resolved_project_name.nil? || resolved_project_name.empty?
|
|
526
|
+
raise "Missing cloudflare.project_name for web flavor '#{flavor}'. Set it in annspec.yaml."
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
unless skip_compile
|
|
530
|
+
unless compile_build(
|
|
531
|
+
flavor: flavor,
|
|
532
|
+
sub_command: "web",
|
|
533
|
+
build_config: build_config,
|
|
534
|
+
main_file: main_file,
|
|
535
|
+
skip_sound_null_safety: skip_sound_null_safety,
|
|
536
|
+
skip_code_sign: true,
|
|
537
|
+
export_options_plist: "",
|
|
538
|
+
platform: @platform,
|
|
539
|
+
)
|
|
540
|
+
raise "Compilation failed for web flavor '#{flavor}'"
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
output_dir = web_output_dir(flavor)
|
|
545
|
+
|
|
546
|
+
case resolved_mode
|
|
547
|
+
when 'pages'
|
|
548
|
+
command_parts = ["wrangler", "pages", "deploy", output_dir,
|
|
549
|
+
"--project-name", resolved_project_name]
|
|
550
|
+
command_parts += ["--branch", resolved_branch] if resolved_branch && !resolved_branch.empty?
|
|
551
|
+
command_parts += ["--commit-dirty", "true"]
|
|
552
|
+
when 'workers'
|
|
553
|
+
config_path = File.join(@root_folder, "web_flavors", flavor, "wrangler.toml")
|
|
554
|
+
command_parts = ["wrangler", "deploy", "--config", config_path]
|
|
555
|
+
else
|
|
556
|
+
raise "Unknown cloudflare mode '#{resolved_mode}'. Use 'pages' or 'workers'."
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
env_overrides = {}
|
|
560
|
+
env_overrides['CLOUDFLARE_ACCOUNT_ID'] = resolved_account_id if resolved_account_id && !resolved_account_id.empty?
|
|
561
|
+
|
|
562
|
+
Fastlane::UI.message("Deploying to Cloudflare #{resolved_mode}: #{command_parts.join(' ')}")
|
|
563
|
+
|
|
564
|
+
Dir.chdir @root_folder do
|
|
565
|
+
env_overrides.each { |k, v| ENV[k] = v }
|
|
566
|
+
Fastlane::Actions::sh(*command_parts)
|
|
567
|
+
env_overrides.keys.each { |k| ENV.delete(k) }
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
@statusManager.logSuccess flavor, "upload_to_cloudflare", @platform
|
|
571
|
+
return true
|
|
572
|
+
|
|
573
|
+
rescue => e
|
|
574
|
+
Fastlane::UI.error "Error while deploying to Cloudflare for web flavor '#{flavor}'"
|
|
575
|
+
Fastlane::UI.error e
|
|
576
|
+
@statusManager.logError flavor, "upload_to_cloudflare", @platform, e
|
|
577
|
+
return false
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
private
|
|
582
|
+
|
|
583
|
+
def web_output_dir(flavor)
|
|
584
|
+
flavor.to_s.empty? ? "build/web" : "build/web/#{flavor}"
|
|
585
|
+
end
|
|
586
|
+
|
|
501
587
|
end
|
|
502
588
|
end
|
|
@@ -377,6 +377,28 @@ module FastlaneFlutterFlavor
|
|
|
377
377
|
config&.dig('admob', 'gms_ads_id') || config&.dig('gms_ads_id')
|
|
378
378
|
end
|
|
379
379
|
|
|
380
|
+
# Returns the resolved Cloudflare config for a web flavor as a Hash with keys:
|
|
381
|
+
# project_name, account_id, branch, mode — cascaded flavor → default → hardcoded fallback.
|
|
382
|
+
# project_name is flavor-only (never inherited from default).
|
|
383
|
+
# @return [Hash] Always returns a Hash; values may be nil if not configured.
|
|
384
|
+
def get_cloudflare_config(platform, flavor_name)
|
|
385
|
+
return {} unless @spec_data
|
|
386
|
+
|
|
387
|
+
platform_key = platform.to_s
|
|
388
|
+
platform_data = @spec_data.dig('app', platform_key)
|
|
389
|
+
return {} unless platform_data.is_a?(Hash)
|
|
390
|
+
|
|
391
|
+
flavor_cf = platform_data.dig('flavor', flavor_name.to_s, 'cloudflare') || {}
|
|
392
|
+
default_cf = platform_data.dig('default', 'cloudflare') || {}
|
|
393
|
+
|
|
394
|
+
{
|
|
395
|
+
'project_name' => flavor_cf['project_name'],
|
|
396
|
+
'account_id' => flavor_cf['account_id'] || default_cf['account_id'],
|
|
397
|
+
'branch' => flavor_cf['branch'] || default_cf['branch'] || 'main',
|
|
398
|
+
'mode' => flavor_cf['mode'] || default_cf['mode'] || 'pages',
|
|
399
|
+
}
|
|
400
|
+
end
|
|
401
|
+
|
|
380
402
|
# For Google Sign-In (annai_auth)
|
|
381
403
|
def get_auth_client_id(platform, flavor_name, build_config)
|
|
382
404
|
config = get_merged_flavor_config(platform, flavor_name)
|
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.
|
|
4
|
+
version: 0.4.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-08-
|
|
11
|
+
date: 2026-08-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: fastlane
|
|
@@ -89,6 +89,7 @@ files:
|
|
|
89
89
|
- lib/fastlane/plugin/ann_flavor_flutter/actions/ann_run_tests_action.rb
|
|
90
90
|
- lib/fastlane/plugin/ann_flavor_flutter/actions/ann_setup_action.rb
|
|
91
91
|
- lib/fastlane/plugin/ann_flavor_flutter/actions/ann_upload_to_app_store_action.rb
|
|
92
|
+
- lib/fastlane/plugin/ann_flavor_flutter/actions/ann_upload_to_cloudflare_action.rb
|
|
92
93
|
- lib/fastlane/plugin/ann_flavor_flutter/actions/ann_upload_to_firebase_action.rb
|
|
93
94
|
- lib/fastlane/plugin/ann_flavor_flutter/actions/ann_upload_to_play_store_action.rb
|
|
94
95
|
- lib/fastlane/plugin/ann_flavor_flutter/helper/lanes_android.rb
|