gowalk-cicd 1.0.104 → 1.0.105
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.
- package/CLAUDE.md +4 -0
- package/README.md +6 -0
- package/action/.daemux-version +1 -1
- package/action/scripts/test_flutter_native_preparation.py +107 -0
- package/android-action/.daemux-version +1 -1
- package/backend-action/.daemux-version +1 -1
- package/package.json +1 -1
- package/templates/deploy.yml +7 -0
package/CLAUDE.md
CHANGED
|
@@ -264,6 +264,10 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
264
264
|
Both Flutter configuration and the Pods helper use that bundle in their child process,
|
|
265
265
|
preserving Podfile.lock and the parent job environment. Deliver the workflow wrapper and
|
|
266
266
|
action helper together; action-only updates cannot repair earlier custom configuration steps.
|
|
267
|
+
Flutter `--config-only` can query Xcode and install Pods before returning. In the workflow,
|
|
268
|
+
generate Flutter inputs with `pub get`, run the locked `native_pods.py` preparation and
|
|
269
|
+
completed graph guard, then configure the release with its existing obfuscation/define flags.
|
|
270
|
+
The graph guard still applies when there is no Podfile. Preserve this order in custom CI.
|
|
267
271
|
- Locked Pod installation retries once only when its own attempt reports curl 18 and a partial-transfer
|
|
268
272
|
symptom. Both attempts share the existing 900-second budget and recheck Podfile, Podfile.lock and
|
|
269
273
|
selected Ruby bundle inputs. TLS/auth/permission, checksum, version and deployment errors never retry.
|
package/README.md
CHANGED
|
@@ -58,6 +58,12 @@ When adopting this update, retain the `native_bundle.py` configuration wrapper i
|
|
|
58
58
|
custom workflows as well as updating the action files. Apps without a Gemfile keep
|
|
59
59
|
their existing CocoaPods runtime.
|
|
60
60
|
|
|
61
|
+
Flutter `--config-only` can query Xcode and invoke `pod install`. The workflow first
|
|
62
|
+
runs `flutter pub get` to generate the Podfile's Flutter inputs, then installs locked
|
|
63
|
+
Pods and verifies the selected workspace before release configuration. Preserve this
|
|
64
|
+
order in customized validation and deployment workflows; updating action directories
|
|
65
|
+
alone cannot repair a configuration step that runs before the action.
|
|
66
|
+
|
|
61
67
|
## Flutter web release
|
|
62
68
|
|
|
63
69
|
The conditional `deploy-web.yml` workflow runs on changes to Flutter source,
|
package/action/.daemux-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.105
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Execute the shipped Flutter preparation shell with real guards and offline tool fixtures."""
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
import tempfile
|
|
8
|
+
import textwrap
|
|
9
|
+
import unittest
|
|
10
|
+
|
|
11
|
+
import native_bundle
|
|
12
|
+
from test_native_dependency_guard import project
|
|
13
|
+
|
|
14
|
+
REPO = Path(__file__).resolve().parents[2]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FlutterPreparationTests(unittest.TestCase):
|
|
18
|
+
def setUp(self):
|
|
19
|
+
temporary = tempfile.TemporaryDirectory(prefix="flutter-native-preparation-")
|
|
20
|
+
self.addCleanup(temporary.cleanup)
|
|
21
|
+
self.root = Path(temporary.name).resolve()
|
|
22
|
+
project(self.root, "ios/Runner.xcodeproj")
|
|
23
|
+
workspace = self.root / "ios/Runner.xcworkspace"
|
|
24
|
+
workspace.mkdir()
|
|
25
|
+
(workspace / "contents.xcworkspacedata").write_text(
|
|
26
|
+
'<Workspace><FileRef location="group:Runner.xcodeproj"/></Workspace>')
|
|
27
|
+
for name in ("Podfile", "Podfile.lock"):
|
|
28
|
+
(self.root / "ios" / name).write_text("fixture lock\n")
|
|
29
|
+
(self.root / "pubspec.yaml").write_text("name: fixture\n")
|
|
30
|
+
for argv in (["git", "init", "-q"], ["git", "add", "."],
|
|
31
|
+
["git", "-c", "user.name=Fixture", "-c", "user.email=fixture@example.invalid",
|
|
32
|
+
"commit", "-qm", "Freeze native fixture"]):
|
|
33
|
+
subprocess.run(argv, cwd=self.root, capture_output=True, check=True)
|
|
34
|
+
actions = self.root / ".github/actions"
|
|
35
|
+
actions.mkdir(parents=True)
|
|
36
|
+
(actions / "swift-app").symlink_to(REPO / "action", target_is_directory=True)
|
|
37
|
+
(actions / "android-app").symlink_to(REPO / "android-action", target_is_directory=True)
|
|
38
|
+
self.env = {**os.environ, "PATH": str(self.root) + os.pathsep + os.environ["PATH"],
|
|
39
|
+
"GITHUB_WORKSPACE": str(self.root), "RUNNER_TEMP": str(self.root / "scratch"),
|
|
40
|
+
"ONBOARDING_PUBLIC_ORIGIN": "https://flow.example.invalid",
|
|
41
|
+
"GOOGLE_STORE_PROXY_URL": "http://fixture:PRIVATE_SENTINEL@127.0.0.1:9"}
|
|
42
|
+
self.install_tools()
|
|
43
|
+
|
|
44
|
+
def executable(self, name, source):
|
|
45
|
+
path = self.root / name
|
|
46
|
+
path.write_text("#!" + sys.executable + "\n" + textwrap.dedent(source))
|
|
47
|
+
path.chmod(0o700)
|
|
48
|
+
|
|
49
|
+
def install_tools(self):
|
|
50
|
+
self.executable("flutter", '''
|
|
51
|
+
import json,sys
|
|
52
|
+
from pathlib import Path
|
|
53
|
+
if sys.argv[1:3] == ["pub", "get"]:
|
|
54
|
+
folder=Path("ios/Flutter");folder.mkdir()
|
|
55
|
+
(folder/"Generated.xcconfig").write_text("generated")
|
|
56
|
+
elif sys.argv[1:3] == ["build", "ios"]:
|
|
57
|
+
Path("configuration.json").write_text(json.dumps(sys.argv[1:]))
|
|
58
|
+
assert Path("ios/pods-ready").is_file(), "Configuration reached before locked Pods"
|
|
59
|
+
else:
|
|
60
|
+
raise SystemExit(9)
|
|
61
|
+
''')
|
|
62
|
+
self.executable("pod", '''
|
|
63
|
+
import json,os,sys
|
|
64
|
+
from pathlib import Path
|
|
65
|
+
assert Path("Flutter/Generated.xcconfig").is_file()
|
|
66
|
+
assert sys.argv[1:] == ["install", "--deployment", "--no-repo-update"]
|
|
67
|
+
assert os.environ["HTTPS_PROXY"].startswith("http://127.0.0.1:")
|
|
68
|
+
Path("pod-called").touch()
|
|
69
|
+
if os.environ.get("FAIL_PODS"):
|
|
70
|
+
raise SystemExit(7)
|
|
71
|
+
Path("pods-ready").touch()
|
|
72
|
+
''')
|
|
73
|
+
|
|
74
|
+
def run_preparation(self):
|
|
75
|
+
body = (REPO / "templates/deploy.yml").read_text().split(
|
|
76
|
+
"- name: Prepare Flutter iOS project\n", 1)[1].split("\n - ", 1)[0]
|
|
77
|
+
script = textwrap.dedent(body.split(" run: |\n", 1)[1])
|
|
78
|
+
result = subprocess.run([sys.executable, native_bundle.__file__, "--folder", "ios",
|
|
79
|
+
"--proxy-helper", str(REPO / "android-action/scripts/play_store_proxy.py"),
|
|
80
|
+
"--", "bash", "--noprofile", "--norc", "-e", "-o", "pipefail", "-c", script],
|
|
81
|
+
cwd=self.root, env=self.env, capture_output=True, text=True, timeout=20)
|
|
82
|
+
self.assertNotIn("PRIVATE_SENTINEL", result.stdout + result.stderr)
|
|
83
|
+
return result
|
|
84
|
+
|
|
85
|
+
def test_locked_pods_precede_configuration_without_losing_release_arguments(self):
|
|
86
|
+
result = self.run_preparation()
|
|
87
|
+
self.assertEqual(result.returncode, 0, result.stdout)
|
|
88
|
+
self.assertTrue((self.root / "ios/pod-called").exists())
|
|
89
|
+
args = json.loads((self.root / "configuration.json").read_text())
|
|
90
|
+
for arg in ("--release", "--no-codesign", "--config-only", "--obfuscate",
|
|
91
|
+
"--split-debug-info=" + str(self.root / "scratch/dart-symbols/ios"),
|
|
92
|
+
"ONBOARDING_PUBLIC_ORIGIN=https://flow.example.invalid"):
|
|
93
|
+
self.assertIn(arg, args)
|
|
94
|
+
self.assertEqual((self.root / "ios/Podfile.lock").read_text(), "fixture lock\n")
|
|
95
|
+
|
|
96
|
+
def test_failed_locked_install_stops_before_flutter_configuration(self):
|
|
97
|
+
self.env["FAIL_PODS"] = "1"
|
|
98
|
+
self.assertNotEqual(self.run_preparation().returncode, 0)
|
|
99
|
+
self.assertTrue((self.root / "ios/pod-called").exists())
|
|
100
|
+
self.assertFalse((self.root / "configuration.json").exists())
|
|
101
|
+
|
|
102
|
+
def test_remote_package_graph_refuses_before_configuration_without_podfile(self):
|
|
103
|
+
(self.root / "ios/Podfile").unlink()
|
|
104
|
+
project(self.root, "ios/Runner.xcodeproj", {"remote": {"isa": "XCRemoteSwiftPackageReference"}})
|
|
105
|
+
self.assertNotEqual(self.run_preparation().returncode, 0)
|
|
106
|
+
self.assertFalse((self.root / "ios/pod-called").exists())
|
|
107
|
+
self.assertFalse((self.root / "configuration.json").exists())
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.105
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.105
|
package/package.json
CHANGED
package/templates/deploy.yml
CHANGED
|
@@ -149,6 +149,13 @@ jobs:
|
|
|
149
149
|
ONBOARDING_PUBLIC_ORIGIN: ${{ vars.ONBOARDING_PUBLIC_ORIGIN }}
|
|
150
150
|
run: |
|
|
151
151
|
flutter pub get
|
|
152
|
+
# Even --config-only can query Xcode and run pod install. Pub generates
|
|
153
|
+
# the Flutter configuration needed by the Podfile without resolving Pods.
|
|
154
|
+
python3 .github/actions/swift-app/scripts/native_pods.py "$GITHUB_WORKSPACE" \
|
|
155
|
+
--container ios/Runner.xcworkspace \
|
|
156
|
+
--proxy-helper .github/actions/android-app/scripts/play_store_proxy.py
|
|
157
|
+
python3 .github/actions/swift-app/scripts/native_dependency_guard.py "$GITHUB_WORKSPACE" \
|
|
158
|
+
--container ios/Runner.xcworkspace
|
|
152
159
|
# Flutter removed the synthetic `package:flutter_gen`, so apps that use
|
|
153
160
|
# AppLocalizations now generate real sources. Nothing else generates them,
|
|
154
161
|
# and analyze/compile fail on the missing import if we skip this.
|