gowalk-cicd 1.0.145 → 1.0.147
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 +44 -61
- package/README.md +28 -42
- package/action/.daemux-version +1 -1
- package/action/action.yml +0 -9
- package/action/scripts/asc_common.py +4 -7
- package/action/scripts/mobile_release_api.cjs +39 -4
- package/action/scripts/native_bundle.py +6 -10
- package/action/scripts/native_dependency_guard.py +2 -2
- package/action/scripts/native_pods.py +4 -10
- package/action/scripts/recover_upload_intent.cjs +125 -0
- package/action/scripts/test_asc_common_timeouts.py +0 -1
- package/action/scripts/test_asc_network_diagnostics.py +10 -21
- package/action/scripts/test_flutter_native_preparation.py +1 -5
- package/action/scripts/test_native_bundle.py +4 -11
- package/action/scripts/test_native_dependency_wiring.py +5 -3
- package/action/scripts/test_native_pods.py +13 -34
- package/action/scripts/test_native_pods_diagnostics.py +1 -1
- package/action/scripts/test_native_pods_retry.py +2 -8
- package/action/scripts/test_native_prepare_evidence.py +3 -3
- package/action/scripts/test_upload_build.py +7 -15
- package/action/scripts/upload_build.py +12 -8
- package/android-action/.daemux-version +1 -1
- package/android-action/action.yml +8 -32
- package/android-action/flutter-setup/action.yml +1 -2
- package/android-action/play-upload/process.cjs +1 -12
- package/android-action/play-upload/run.cjs +2 -2
- package/android-action/scripts/crashlytics_bootstrap.py +2 -2
- package/android-action/scripts/crashlytics_bootstrap_test_support.py +54 -27
- package/android-action/scripts/crashlytics_symbols.py +5 -3
- package/android-action/scripts/flutter_manifest.py +1 -3
- package/android-action/scripts/flutter_manifest_fixture.py +58 -1
- package/android-action/scripts/play_inventory.py +3 -3
- package/android-action/scripts/play_preflight.py +2 -2
- package/android-action/scripts/test_android_build_diagnostics.py +5 -8
- package/android-action/scripts/test_crashlytics_bootstrap.py +7 -29
- package/android-action/scripts/test_crashlytics_symbols.py +1 -2
- package/android-action/scripts/test_flutter_archive.py +23 -25
- package/android-action/scripts/test_flutter_archive_cache.py +7 -25
- package/android-action/scripts/test_flutter_archive_setup.py +5 -6
- package/android-action/scripts/test_flutter_archive_size.py +3 -3
- package/android-action/scripts/test_flutter_cache_setup.py +7 -24
- package/android-action/scripts/test_flutter_manifest.py +20 -39
- package/android-action/scripts/test_flutter_manifest_scope.py +8 -6
- package/android-action/scripts/test_flutter_origin_retry.py +66 -0
- package/android-action/scripts/test_flutter_release_cache.py +13 -22
- package/android-action/scripts/test_play_inventory.py +1 -1
- package/android-action/scripts/test_play_preflight.py +0 -8
- package/backend-action/.daemux-version +1 -1
- package/package.json +1 -1
- package/src/config/build-steps.mjs +7 -3
- package/templates/deploy-web.yml +1 -4
- package/templates/deploy.yml +4 -11
- package/templates/history.json.gz +0 -0
- package/action/scripts/apple_store_proxy.py +0 -28
- package/action/scripts/test_apple_store_proxy.py +0 -44
- package/android-action/scripts/jvm_proxy_relay.py +0 -166
- package/android-action/scripts/play_proxy_test_support.py +0 -82
- package/android-action/scripts/play_store_proxy.py +0 -109
- package/android-action/scripts/test_crashlytics_symbols_proxy.py +0 -54
- package/android-action/scripts/test_flutter_proxy_retry.py +0 -83
- package/android-action/scripts/test_flutter_test_loopback.py +0 -73
- package/android-action/scripts/test_google_bootstrap_proxy.py +0 -77
- package/android-action/scripts/test_google_bootstrap_wiring.py +0 -140
- package/android-action/scripts/test_jvm_proxy_cleanup.py +0 -44
- package/android-action/scripts/test_jvm_proxy_idle.py +0 -106
- package/android-action/scripts/test_jvm_proxy_loopback.py +0 -91
- package/android-action/scripts/test_jvm_proxy_relay.py +0 -148
- package/android-action/scripts/test_play_connect_runtime.py +0 -62
- package/android-action/scripts/test_play_preflight_proxy_runtime.py +0 -58
- package/android-action/scripts/test_play_store_proxy.py +0 -98
- package/android-action/scripts/test_relay_half_close.py +0 -148
package/CLAUDE.md
CHANGED
|
@@ -104,19 +104,20 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
104
104
|
Detect and warn, tell the user to remove lines manually.
|
|
105
105
|
- Never repeat an `env:` key in another case (`NO_PROXY` beside `no_proxy`): GitHub
|
|
106
106
|
compares env keys case-insensitively and rejects the whole workflow or action file.
|
|
107
|
-
`test/env-keys.test.mjs` scans the templates and actions.
|
|
108
|
-
|
|
109
|
-
process) or `play_store_proxy.py --github-env` (later steps), never through YAML.
|
|
107
|
+
`test/env-keys.test.mjs` scans the templates and actions. Where a step genuinely needs
|
|
108
|
+
both spellings of a variable, set them inside the step's own child process, never in YAML.
|
|
110
109
|
- Composite action steps cannot use workflow-only `timeout-minutes`. Native cache restores
|
|
111
110
|
retain their segment timeout and the caller's job deadline; workflow-level cache steps
|
|
112
111
|
can retain their two-minute step limits. `test/composite-timeouts.test.mjs` guards this schema boundary.
|
|
113
112
|
- Store API calls belong in GitHub Actions. Local tests may build/sign but must
|
|
114
113
|
never connect to App Store Connect or Google Play.
|
|
115
|
-
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
- **GitHub Actions reaches Apple and Google directly, and must never be given a store
|
|
115
|
+
proxy.** The account-pinned residential exit exists so that the panel and the runner
|
|
116
|
+
Macs are not the hosts contacting the stores; a GitHub-hosted runner is neither.
|
|
117
|
+
No workflow, action or helper here may read `APPLE_STORE_PROXY_URL`,
|
|
118
|
+
`GOOGLE_STORE_PROXY_URL`, or set `HTTP(S)_PROXY` for a build tool — the job-wide
|
|
119
|
+
transport this replaced billed every SDK, pub, Gradle and CocoaPods byte to a metered
|
|
120
|
+
residential exit. Apple IPA uploads use `action/scripts/upload_build.py`, not native upload tools.
|
|
120
121
|
It retains provider IDs/local SHA-256 and verifies matching IPA identity before resume.
|
|
121
122
|
Finalization sends `uploaded:true` as Apple's documented BuildUpload flow does; the
|
|
122
123
|
IPA endpoint rejected the optional SHA_256 checksum attribute despite the generic
|
|
@@ -143,51 +144,31 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
143
144
|
A certificate POST's HTTP 409 alone does not prove a full cap. `certificate_failure.py`
|
|
144
145
|
emits fixed reason/code evidence in `apple_certificate_rejected`; raw provider details stay private.
|
|
145
146
|
Certificate creation sends the complete PEM CSR in `csrContent`, including its framing and newlines.
|
|
146
|
-
- Keep preinstalled Android SDK/NDKs.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
Crashlytics Buildtools reads them first and rejects authenticated proxy URLs. HTTPS is tunneled
|
|
151
|
-
without TLS interception; no upstream failure may fall back to the destination.
|
|
152
|
-
Java bypasses the relay only for exact `localhost`, `127.0.0.1` and `[::1]`
|
|
153
|
-
targets so owned HTTP test fixtures remain local. Never widen that host list;
|
|
154
|
-
external requests and environment-first clients retain the assigned relay.
|
|
155
|
-
The wrapper disables Gradle daemons and closes its relay when the command ends.
|
|
156
|
-
The relay's idle deadline covers the whole tunnel: traffic in either direction
|
|
157
|
-
keeps downloads/uploads alive. An idle direction alone must never end a transfer.
|
|
158
|
-
A clean directional EOF forwards a half-close when the transport supports it and
|
|
159
|
-
leaves the opposite stream alive until completion, error or the shared idle deadline.
|
|
160
|
-
Never cancel an unfinished reply or upload merely because the other pump completed.
|
|
161
|
-
- Flutter bootstrap is part of that boundary: before the Flutter setup action,
|
|
162
|
-
`play_store_proxy.py --bootstrap-env` validates the Google account pin and writes
|
|
163
|
-
both proxy/bypass spellings to the private job environment without console output.
|
|
164
|
-
SDK manifest/archive curl requests use that pin. Subsequent pub, analysis, tests,
|
|
165
|
-
localization, global activation and builds run through the existing owned relay.
|
|
166
|
-
The helper's bootstrap and command modes require only Python's standard library;
|
|
167
|
-
importing the Google API client must not become an unprotected bootstrap prerequisite.
|
|
147
|
+
- Keep preinstalled Android SDK/NDKs. Gradle tests/builds, SDK downloads, pub, analysis,
|
|
148
|
+
localization and Flutter bootstrap all run with the job's own environment and reach their
|
|
149
|
+
providers directly. Do not reintroduce a relay, a wrapper shell or a proxy variable for
|
|
150
|
+
them: those existed only to force traffic through an account exit CI no longer uses.
|
|
168
151
|
- `android-action/flutter-setup/` owns Flutter setup. It forwards the official action's
|
|
169
152
|
inputs/cache identities while isolating restore/save from provider transport. Its step-local
|
|
170
153
|
`NODE_OPTIONS` preloader (`android-action/scripts/cache_*.cjs`) also protects CocoaPods cache
|
|
171
154
|
steps and verifies the exact pinned Actions cache entrypoint bytes and HTTPS
|
|
172
|
-
GitHub cache/Azure blob destinations before
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
`NO_PROXY`. The preloader snapshot under `RUNNER_TEMP` also covers official post/save after
|
|
155
|
+
GitHub cache/Azure blob destinations before the cache process runs. Unknown code or
|
|
156
|
+
origins refuse. The preloader stays scoped to that one process: never export it through
|
|
157
|
+
`GITHUB_ENV`. The preloader snapshot under `RUNNER_TEMP` also covers official post/save after
|
|
176
158
|
older consumer autoupdate changes the action directory. The installer delivers this development
|
|
177
159
|
tooling for native iOS repositories too; it does not require an Android app.
|
|
178
160
|
- Flutter manifest/archive GET recovery is scoped to the two pinned setup invocations through `BASH_ENV`.
|
|
179
|
-
It
|
|
180
|
-
for archives, with an 8 GiB archive bound. Interrupted archives resume private bytes with HTTP Range; an origin ignoring
|
|
161
|
+
It allows four attempts within 60 seconds for manifests or 20 minutes for archives, with an 8 GiB archive bound. Interrupted archives resume private bytes with HTTP Range; an origin ignoring
|
|
181
162
|
Range permits a bounded full restart. Only complete JSON or an archive matching the selected official
|
|
182
|
-
manifest's SHA-256 enters action outputs.
|
|
183
|
-
|
|
163
|
+
manifest's SHA-256 enters action outputs. A transient origin refusal (408, 429, 500, 502, 503,
|
|
164
|
+
504) shares that retry budget. Authentication/certificate refusals remain terminal.
|
|
184
165
|
`flutter_download_failed` emits fixed transport codes and retained-byte counts, never curl stderr.
|
|
185
166
|
Archive progress emits retained byte counts every minute and safe results after each attempt;
|
|
186
167
|
the transfer deadline leaves room for a failure receipt before a 30-minute validation job ends.
|
|
187
168
|
With SDK caching enabled, failed archive transfers preserve public bytes in a job-owned,
|
|
188
169
|
digest-scoped directory. Separate optional cache restore/save steps retain them between runs;
|
|
189
170
|
they never expose partial bytes as an installed SDK. Successful or corrupt completed archives
|
|
190
|
-
are removed from that partial cache. Full SDK cache identities
|
|
171
|
+
are removed from that partial cache. Full SDK cache identities stay unchanged.
|
|
191
172
|
- Web Release selects bundled renderer resources with `--no-web-resources-cdn` inside
|
|
192
173
|
the existing proxied build command. This is not a font or integration offline guarantee;
|
|
193
174
|
preserve app-authored font declarations, bootstrap configuration and other build inputs.
|
|
@@ -218,9 +199,8 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
218
199
|
only verified matching binaries with current credentials and retains the original build/symbol identity;
|
|
219
200
|
a miss uses the normal build without waiting. Preserve successful sibling artifacts across reruns.
|
|
220
201
|
See `docs/CANDIDATE_ARTIFACTS.md`; never turn this optimization into a new factory stage or resource reservation.
|
|
221
|
-
It reuses the cache transport's approved HTTPS request guard
|
|
222
|
-
|
|
223
|
-
later Apple/Google clients retain their proxies and artifact failures remain job failures.
|
|
202
|
+
It reuses the cache transport's approved HTTPS request guard inside the official
|
|
203
|
+
`upload-artifact` process. Unknown programs/origins refuse; artifact failures remain job failures.
|
|
224
204
|
The iOS action reads this helper from its immutable `SWIFT_APP_ACTION` snapshot. Its shared
|
|
225
205
|
`cache_scope.cjs` and `artifact_env.cjs` copies match the Android distribution byte for byte,
|
|
226
206
|
enforced by `test/artifact-wiring.test.mjs`; update both when changing that common guard.
|
|
@@ -266,12 +246,12 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
266
246
|
is the only place that decides which; every downstream step branches on the
|
|
267
247
|
`project_kind` output rather than re-sniffing the repo. Flutter wins the tie
|
|
268
248
|
because a Flutter app also carries `android/settings.gradle`.
|
|
269
|
-
- Both Android release compilers run through `android_build_diagnostics.py
|
|
270
|
-
|
|
249
|
+
- Both Android release compilers run through `android_build_diagnostics.py`.
|
|
250
|
+
It retains at most 64 KiB of private child output and publishes
|
|
271
251
|
only fixed signal names, phase and exit status in `android_build_failed`. An empty signal
|
|
272
252
|
list is unclassified, never a guessed cause; matching signals are observations, not a retry
|
|
273
253
|
decision. Minute progress notices replace raw compiler output. Preserve the actual exit,
|
|
274
|
-
command arguments,
|
|
254
|
+
command arguments, signing and symbol checks.
|
|
275
255
|
- iOS plist stamping reads complete JSON build settings through `resolve_info_plist.py`,
|
|
276
256
|
preserving Xcode's exit status and bounded sanitized stderr. Select exactly the configured
|
|
277
257
|
bundle's application target and resolve paths from that target's source root; never take
|
|
@@ -281,15 +261,15 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
281
261
|
updates, retain inherited proxies, and never enable provisioning network operations.
|
|
282
262
|
- Native Xcode validation and archives first check the selected project/workspace graph with
|
|
283
263
|
`native_dependency_guard.py ROOT --container PATH`. Xcode-managed Swift packages remain refused:
|
|
284
|
-
|
|
264
|
+
they resolve outside the committed lockfile the guard exists to enforce. The same app session preserves
|
|
285
265
|
source and uses the vendor's official CocoaPods distribution or verified local XCFrameworks.
|
|
286
|
-
`native_pods.py` installs a committed, unchanged `Podfile.lock` with `pod install --deployment
|
|
287
|
-
|
|
288
|
-
|
|
266
|
+
`native_pods.py` installs a committed, unchanged `Podfile.lock` with `pod install --deployment`,
|
|
267
|
+
then checks the completed workspace. No Podfile means no dependency download at all.
|
|
268
|
+
Initial local lock resolution may use the
|
|
289
269
|
explicit `--before-pods --initial-pods-lock` guard; CI never uses that development exception.
|
|
290
270
|
These checks cover the declared native dependency graph, not arbitrary custom build-script traffic.
|
|
291
271
|
`native_bundle.py` honors the selected project's committed Gemfile/lock, falling back to
|
|
292
|
-
the repository root; missing gems install
|
|
272
|
+
the repository root; missing gems install with a frozen bundle.
|
|
293
273
|
Both Flutter configuration and the Pods helper use that bundle in their child process,
|
|
294
274
|
preserving Podfile.lock and the parent job environment. Deliver the workflow wrapper and
|
|
295
275
|
action helper together; action-only updates cannot repair earlier custom configuration steps.
|
|
@@ -339,10 +319,8 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
339
319
|
must not discard the symbols of a build that is already live. Symbol
|
|
340
320
|
artifacts carry no `retention-days` so the repository's setting governs and
|
|
341
321
|
can be raised to cover a release's life.
|
|
342
|
-
- Firebase Crashlytics traffic
|
|
343
|
-
|
|
344
|
-
2.9.2+ and the pinned buildtools support it; generic JVM networking uses the relay.
|
|
345
|
-
Native iOS upload-symbols uses NSURLSession, so it is never executed. Before
|
|
322
|
+
- Firebase Crashlytics traffic leaves the runner directly, like every other provider
|
|
323
|
+
request in CI. Native iOS upload-symbols uses NSURLSession, so it is never executed. Before
|
|
346
324
|
archiving, dedicated Crashlytics upload phases in the ephemeral Xcode projects
|
|
347
325
|
are deferred; mixed/unidentified upload phases refuse the archive for repair.
|
|
348
326
|
CI retains the archive's dSYMs as a ZIP with UUIDs, source SHA and SHA-256, then
|
|
@@ -351,18 +329,18 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
351
329
|
account-pinned Firebase console, reading processing back before completing the
|
|
352
330
|
delivery request. This requires no human handoff. A green CI run alone is not
|
|
353
331
|
evidence that the deferred symbols reached Firebase. Android retains its Dart
|
|
354
|
-
symbols and uploads them before the store bundle
|
|
332
|
+
symbols and uploads them before the store bundle.
|
|
355
333
|
- Crashlytics buildtools bootstrap runs before Flutter compilation. `crashlytics_bootstrap.py`
|
|
356
334
|
pins the official JAR version, byte size and SHA-256, admits only verified dependency-cache
|
|
357
|
-
bytes, and bounds
|
|
335
|
+
bytes, and bounds GET recovery to three attempts within three minutes. Java receives
|
|
358
336
|
that verified file through `CRASHLYTICS_LOCAL_JAR`; changing the Firebase CLI pin must check
|
|
359
337
|
its JAR version/override contract. TLS, authorization and checksum errors never retry.
|
|
360
338
|
`firebase_symbols_bootstrap_failed` carries fixed typed evidence, never private curl output.
|
|
361
339
|
- Play readiness and AAB/APK version inventory share one prebuild edit. Retry OAuth
|
|
362
340
|
transport, inventory reads and cleanup of that known edit; never replay an ambiguous
|
|
363
341
|
`edits.insert`. Edit creation retries at most three times only for typed connection-timeout
|
|
364
|
-
or typed connection failure
|
|
365
|
-
|
|
342
|
+
or typed connection failure evidence that no provider request was sent. TLS verification
|
|
343
|
+
failures, provider responses and lost origin responses do not authorize a retry.
|
|
366
344
|
Only an explicit package-404 allows first-release defaults; failed
|
|
367
345
|
inventory is not an empty account. The action exposes `play-api-ready` so current
|
|
368
346
|
workflows skip the redundant postbuild check. Error annotations carry safe
|
|
@@ -392,7 +370,7 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
392
370
|
bytes before running Node24. It classifies immediate private child output, never live
|
|
393
371
|
GitHub annotations: expired/deleted retries normally; only the exact cannot-auto-submit
|
|
394
372
|
refusal permits a review hold. Unknown/transport/post-commit uncertainty does not replay.
|
|
395
|
-
The existing signed AAB,
|
|
373
|
+
The existing signed AAB, track/status/rollout and notes survive one bounded retry;
|
|
396
374
|
only a successful hold emits `play_review_pending`. Keep raw child output out of receipts.
|
|
397
375
|
Each attempt also emits brace-free `play_upload_diagnostic` with fixed observed progress,
|
|
398
376
|
process outcome and error signals from bounded private stdout/stderr line buffers.
|
|
@@ -424,8 +402,8 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
424
402
|
only exact terminal run/attempt/source proof permits CI-owner recovery.
|
|
425
403
|
Both entrypoints emit brace-free `play_edit_owner` errors with fixed codes and optional child
|
|
426
404
|
exit evidence, preserving the existing upload receipt and refusal. Never reconstruct masked text.
|
|
427
|
-
Other packages stay parallel. The GitHub coordination request is fixed-origin
|
|
428
|
-
|
|
405
|
+
Other packages stay parallel. The GitHub coordination request is fixed-origin.
|
|
406
|
+
Update workflow wiring as well as action directories.
|
|
429
407
|
|
|
430
408
|
- Mobile Deploy watches `.factory/releases/mobile.json`, produced from committed task source and
|
|
431
409
|
the named build-variable allow-list shared by freeze and runtime in `mobile_inputs.cjs`.
|
|
@@ -435,6 +413,11 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
435
413
|
recorded immediately in repository deployment receipts; retries reuse their prior-run evidence.
|
|
436
414
|
An uncertain upload never starts another binary automatically. Preserve its signed artifact,
|
|
437
415
|
complete exact provider readback/recovery through scoped tooling, then reconcile its receipt.
|
|
416
|
+
`action/scripts/recover_upload_intent.cjs owner/repo deployment-id plan|live` repairs only
|
|
417
|
+
an iOS intent whose exact terminal run has one failed HTTP 500 intent step and an explicitly
|
|
418
|
+
skipped uploader in the complete GitHub job log. It refuses later run attempts and changed
|
|
419
|
+
evidence, appends a read-back building receipt, and never uploads or calls Apple. Retry the
|
|
420
|
+
original failed job afterward; preserve the recovery proof separately.
|
|
438
421
|
The local Android workflow supplies `mobileReleaseIntentScript` to the upload wrapper instead
|
|
439
422
|
of marking `uploading` before acquiring Play ownership. A refused owner leaves the release
|
|
440
423
|
record at `building`; the wrapper records intent inside its acquired lease before provider
|
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ action-only updates do not change triggers. Preserve custom build inputs and rea
|
|
|
78
78
|
|
|
79
79
|
Flutter's optional SDK and pub cache restores have a one-minute timeout per
|
|
80
80
|
download segment. A slow segment becomes a cache miss and normal SDK setup
|
|
81
|
-
continues
|
|
81
|
+
continues normally; SDK setup errors still fail the
|
|
82
82
|
job. This bounds individual cache segments, not the total cache or SDK download,
|
|
83
83
|
and keeps existing cache keys. A successfully installed SDK is saved before app
|
|
84
84
|
checks run, so a later test/build failure does not force another cold SDK download.
|
|
@@ -401,12 +401,13 @@ successful preparation reports `pod_attempts`. Dependency locks, relay and TLS c
|
|
|
401
401
|
SDK transfers also emit `flutter_download_progress` notices with schema
|
|
402
402
|
`gowalk-cicd/flutter-download-progress.v1`. Each carries `phase`, `event`, `elapsed_ms`
|
|
403
403
|
and `retained_bytes`; `attempt_finished` adds `attempt`, `curl_exit`, `http_status`
|
|
404
|
-
and `proxy_status
|
|
404
|
+
and `proxy_status` (retained for schema compatibility; always 0 now that CI reaches
|
|
405
|
+
providers directly). In-progress notices arrive each minute; elapsed time belongs to
|
|
405
406
|
the current attempt. Archives have a 20-minute total transfer budget so a failure
|
|
406
407
|
receipt precedes a 30-minute validation job's deadline. Progress is not a success receipt.
|
|
407
408
|
When SDK caching is enabled, an exhausted transfer preserves its partial public archive for
|
|
408
409
|
the next run under a separate release-specific cache key. Resumption still uses the selected
|
|
409
|
-
official manifest digest
|
|
410
|
+
official manifest digest; only a verified complete archive
|
|
410
411
|
can reach SDK extraction. Partial-cache restore uses the existing one-minute cache segment
|
|
411
412
|
bound. Optional cache operations do not extend the transfer deadline or turn a failed installation green.
|
|
412
413
|
|
|
@@ -442,8 +443,8 @@ standalone preflight. Refreshing the workflow alongside actions removes that lat
|
|
|
442
443
|
|
|
443
444
|
The API readiness preflight retries transient OAuth transport failures and cleanup of
|
|
444
445
|
its own known edit up to three times, with one- and two-second delays. It never
|
|
445
|
-
replays an edit creation whose outcome is unknown.
|
|
446
|
-
|
|
446
|
+
replays an edit creation whose outcome is unknown. An absent edit after cleanup is
|
|
447
|
+
already closed. Exhausted recovery
|
|
447
448
|
emits the `play_preflight_failed` error annotation with schema
|
|
448
449
|
`gowalk-cicd/play-preflight-failure.v1`, phase (`oauth_refresh`, `edit_create`,
|
|
449
450
|
`version_inventory` or `edit_cleanup`), classified code and attempt count. Provider bodies, credential
|
|
@@ -453,8 +454,8 @@ edit ID and `cleanup_required: true` so recovery targets that edit.
|
|
|
453
454
|
The upload wrapper at `android-action/play-upload/` runs the unchanged official
|
|
454
455
|
`r0adkll/upload-google-play` revision `e738b9dd8f2476ea806d921b64aacd24f34515a5` in
|
|
455
456
|
Node24. Its fixed GitHub download is checked against the recorded size and SHA256
|
|
456
|
-
before execution; an absent or changed program refuses upload.
|
|
457
|
-
|
|
457
|
+
before execution; an absent or changed program refuses upload. The subprocess inherits
|
|
458
|
+
the job's own environment and reaches Google directly.
|
|
458
459
|
|
|
459
460
|
The wrapper permits at most two attempts within one hour, reusing the existing
|
|
460
461
|
signed bundle, track, status, rollout fraction and release notes:
|
|
@@ -520,15 +521,8 @@ and after. Linux only; skipped in Bitrise mode. npm survives on purpose: the
|
|
|
520
521
|
the Firebase CLI through `npx`.
|
|
521
522
|
|
|
522
523
|
The preinstalled Android SDK and NDKs are retained. Gradle and SDK-manager Java
|
|
523
|
-
networking
|
|
524
|
-
|
|
525
|
-
HTTPS remains an end-to-end TLS tunnel. An unavailable proxy fails the request,
|
|
526
|
-
and the relay shuts down with its child command. Gradle daemons are disabled for
|
|
527
|
-
these commands so they cannot retain an expired relay port.
|
|
528
|
-
Java requests to exact `localhost`, `127.0.0.1` and `[::1]` targets stay local for
|
|
529
|
-
HTTP test fixtures. All other Java hosts, including lookalike names such as
|
|
530
|
-
`localhost.example.com`, retain the assigned proxy; environment-first clients
|
|
531
|
-
continue to use the relay.
|
|
524
|
+
networking reaches Google directly, like every other provider request in CI.
|
|
525
|
+
Gradle daemons stay disabled for these commands.
|
|
532
526
|
|
|
533
527
|
### Private git dependencies (Flutter)
|
|
534
528
|
|
|
@@ -775,16 +769,13 @@ directory to that service from your own pipeline.
|
|
|
775
769
|
|
|
776
770
|
Set the repository variable to the Firebase App IDs for the shipping platforms
|
|
777
771
|
(`1:<project>:ios:<hash>` and/or `1:<project>:android:<hash>`). The workflow passes it
|
|
778
|
-
as the `firebase-app-id` input.
|
|
779
|
-
repository secret before any provider operation.
|
|
772
|
+
as the `firebase-app-id` input.
|
|
780
773
|
|
|
781
|
-
Android builds and the pinned Firebase CLI
|
|
782
|
-
|
|
783
|
-
environment variables; older versions must be updated before use. Dart symbols are
|
|
784
|
-
retained as artifacts and uploaded through that transport before the bundle ships.
|
|
774
|
+
Android builds and the pinned Firebase CLI upload Crashlytics mapping and native symbols
|
|
775
|
+
directly. Dart symbols are retained as artifacts and uploaded before the bundle ships.
|
|
785
776
|
|
|
786
|
-
Before Flutter compilation, the action downloads Crashlytics buildtools 3.0.3
|
|
787
|
-
|
|
777
|
+
Before Flutter compilation, the action downloads Crashlytics buildtools 3.0.3 and
|
|
778
|
+
verifies its exact size and SHA-256. Verified bytes are
|
|
788
779
|
reused from the runner dependency cache and supplied through the Firebase CLI's
|
|
789
780
|
`CRASHLYTICS_LOCAL_JAR` override. GET recovery allows three attempts within three minutes;
|
|
790
781
|
TLS, authorization and checksum refusals stop immediately. A bootstrap failure emits
|
|
@@ -806,26 +797,22 @@ is required. A completed CI run does not mean this deferred upload is complete.
|
|
|
806
797
|
|
|
807
798
|
The iOS composite action runs on `macos-15` and:
|
|
808
799
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
operations in iOS, Android and web workflows. Bootstrap validates it before SDK setup;
|
|
816
|
-
subsequent Dart and JVM operations use the same owned relay as release builds. A fork
|
|
817
|
-
without the repository secret cannot start provider downloads through these workflows.
|
|
800
|
+
GitHub Actions reaches Apple and Google **directly**. No store proxy is configured, read
|
|
801
|
+
or inherited here: the account-pinned residential exit belongs to the panel and the runner
|
|
802
|
+
Macs, which are the hosts that must not appear to the stores as generic infrastructure.
|
|
803
|
+
`APPLE_STORE_PROXY_URL` and `GOOGLE_STORE_PROXY_URL` are no longer used by any workflow,
|
|
804
|
+
action or helper, and must not be reintroduced. Refresh existing workflow files with the
|
|
805
|
+
released installer while preserving application-specific build inputs.
|
|
818
806
|
The Apple uploader retains `apple-upload-<run>-<attempt>` receipts with IPA SHA-256,
|
|
819
807
|
upload ID and processing readback, and resumes matching bytes after interruption.
|
|
820
808
|
|
|
821
809
|
GitHub artifact traffic uses a separate, per-action transport scope. The exact pinned
|
|
822
810
|
`actions/upload-artifact` client can reach approved GitHub Results and artifact-storage
|
|
823
|
-
HTTPS origins
|
|
824
|
-
|
|
825
|
-
exit, and a failed artifact creation, transfer or finalization still fails delivery.
|
|
811
|
+
HTTPS origins; unknown programs and destinations are refused. The scope ends with that
|
|
812
|
+
Node process, and a failed artifact creation, transfer or finalization still fails delivery.
|
|
826
813
|
Adoption requires updating workflow upload steps as well as the distributed actions while
|
|
827
|
-
preserving each app's custom checks and artifact retention settings.
|
|
828
|
-
|
|
814
|
+
preserving each app's custom checks and artifact retention settings. An isolated
|
|
815
|
+
`ECONNRESET` does not identify every possible network fault.
|
|
829
816
|
|
|
830
817
|
1. **Auto-detects** your `.xcodeproj` / `.xcworkspace`, scheme, bundle ID,
|
|
831
818
|
and `team_id` (from the ASC API key). No `ci.config.yaml` required —
|
|
@@ -843,7 +830,7 @@ inherited-proxy path; an isolated `ECONNRESET` does not identify every possible
|
|
|
843
830
|
`CI-<bundle_id>`. Patches the `.pbxproj` to use Manual signing against those
|
|
844
831
|
profiles.
|
|
845
832
|
6. **Archives** with `xcodebuild archive`, exports the IPA, and uploads via
|
|
846
|
-
Apple's build-upload REST API
|
|
833
|
+
Apple's build-upload REST API.
|
|
847
834
|
7. **Sets "What's New"** on every declared localization (reads
|
|
848
835
|
`fastlane/metadata/ios/<locale>/release_notes.txt` if present, or from the
|
|
849
836
|
`app-store-whats-new` input).
|
|
@@ -1205,7 +1192,7 @@ A completed file is reused only when its content-derived filename and size match
|
|
|
1205
1192
|
any returned file checksum is verified.
|
|
1206
1193
|
|
|
1207
1194
|
A failed upload emits the typed `apple_build_upload_failed` error annotation with schema
|
|
1208
|
-
`gowalk-cicd/apple-build-upload-failed.v2`: `category` (`
|
|
1195
|
+
`gowalk-cicd/apple-build-upload-failed.v2`: `category` (`ipa_invalid`,
|
|
1209
1196
|
`configuration_missing`, `app_mismatch`, `provider_request_failed`, `upload_identity_conflict`,
|
|
1210
1197
|
`upload_destination_invalid`, `ipa_changed`, `part_refused`, `processing_failed`,
|
|
1211
1198
|
`processing_pending`, or a fallback such as `local_io`), `stage`, `receipt_available` and
|
|
@@ -1216,9 +1203,8 @@ published. The job also retains the exact exported IPA as `apple-ipa-<run>-<atte
|
|
|
1216
1203
|
different bytes under the same number. Build numbers come from `/builds`,
|
|
1217
1204
|
`/preReleaseVersions` **and** `/apps/{id}/buildUploads`, so an unfinished or refused
|
|
1218
1205
|
reservation is never reused; delete such a reservation only after reading it back.
|
|
1219
|
-
All requests and parts still use the Apple proxy.
|
|
1220
1206
|
|
|
1221
|
-
Flutter SDK setup retries interrupted manifest and archive GETs
|
|
1207
|
+
Flutter SDK setup retries interrupted manifest and archive GETs, with four attempts
|
|
1222
1208
|
within 60 seconds for manifests or 30 minutes for archives, with an 8 GiB archive bound. Retries resume private bytes
|
|
1223
1209
|
with HTTP Range; if the origin ignores Range, a bounded full restart is permitted. The completed archive
|
|
1224
1210
|
must match the selected official manifest's SHA-256 before extraction. Authentication and certificate
|
package/action/.daemux-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.147
|
package/action/action.yml
CHANGED
|
@@ -204,14 +204,6 @@ runs:
|
|
|
204
204
|
rm -rf "$RUNNER_TEMP/swift-app-action"
|
|
205
205
|
mkdir -p "$RUNNER_TEMP/swift-app-action"
|
|
206
206
|
cp -R "${{ github.action_path }}/." "$RUNNER_TEMP/swift-app-action/"
|
|
207
|
-
# Native repositories receive the same canonical Google transport as Android.
|
|
208
|
-
mkdir -p "$RUNNER_TEMP/swift-app-action/google-transport"
|
|
209
|
-
for helper in play_store_proxy.py jvm_proxy_relay.py; do
|
|
210
|
-
if [ -f "$GITHUB_WORKSPACE/.github/actions/android-app/scripts/$helper" ]; then
|
|
211
|
-
cp "$GITHUB_WORKSPACE/.github/actions/android-app/scripts/$helper" \
|
|
212
|
-
"$RUNNER_TEMP/swift-app-action/google-transport/$helper"
|
|
213
|
-
fi
|
|
214
|
-
done
|
|
215
207
|
echo "SWIFT_APP_ACTION=$RUNNER_TEMP/swift-app-action" >> "$GITHUB_ENV"
|
|
216
208
|
|
|
217
209
|
# The plugin self-update runs BEFORE the version, signing and archive
|
|
@@ -359,7 +351,6 @@ runs:
|
|
|
359
351
|
fi
|
|
360
352
|
if ! python3 "$SWIFT_APP_ACTION/scripts/native_pods.py" "$GITHUB_WORKSPACE" \
|
|
361
353
|
--container "${INPUT_WORKSPACE:-$INPUT_PROJECT}" \
|
|
362
|
-
--proxy-helper "$SWIFT_APP_ACTION/google-transport/play_store_proxy.py" \
|
|
363
354
|
> "$RUNNER_TEMP/native-pods.json"; then
|
|
364
355
|
cat "$RUNNER_TEMP/native-pods.json"
|
|
365
356
|
exit 1
|
|
@@ -16,8 +16,6 @@ from typing import Any
|
|
|
16
16
|
import jwt
|
|
17
17
|
import requests
|
|
18
18
|
|
|
19
|
-
from apple_store_proxy import proxies
|
|
20
|
-
|
|
21
19
|
|
|
22
20
|
ASC_BASE = "https://api.appstoreconnect.apple.com/v1"
|
|
23
21
|
|
|
@@ -156,9 +154,8 @@ def _request_timeouts() -> tuple[float, float]:
|
|
|
156
154
|
|
|
157
155
|
|
|
158
156
|
def _network_error_category(exc: BaseException) -> str:
|
|
159
|
-
"""Closed diagnostic labels only; exception text can contain private
|
|
157
|
+
"""Closed diagnostic labels only; exception text can contain private URLs."""
|
|
160
158
|
for error_type, category in (
|
|
161
|
-
(requests.exceptions.ProxyError, "proxy"),
|
|
162
159
|
(requests.exceptions.SSLError, "tls"),
|
|
163
160
|
(requests.exceptions.ConnectTimeout, "connect_timeout"),
|
|
164
161
|
(requests.exceptions.ReadTimeout, "read_timeout"),
|
|
@@ -180,11 +177,11 @@ def _retry_network_error(
|
|
|
180
177
|
if attempt >= total - 1:
|
|
181
178
|
raise SystemExit(
|
|
182
179
|
f"ASC {method} {path} network error after {total} "
|
|
183
|
-
f"attempts
|
|
180
|
+
f"attempts (category={category})"
|
|
184
181
|
)
|
|
185
182
|
delay = backoffs[attempt]
|
|
186
183
|
print(
|
|
187
|
-
f"ASC {method} {path} network error
|
|
184
|
+
f"ASC {method} {path} network error; "
|
|
188
185
|
f"retrying in {delay}s ({attempt + 1}/{total - 1}; category={category})",
|
|
189
186
|
file=sys.stderr,
|
|
190
187
|
)
|
|
@@ -240,7 +237,7 @@ def request(
|
|
|
240
237
|
try:
|
|
241
238
|
resp = requests.request(
|
|
242
239
|
method, url, headers=headers, params=params,
|
|
243
|
-
json=json_body, timeout=timeout,
|
|
240
|
+
json=json_body, timeout=timeout,
|
|
244
241
|
)
|
|
245
242
|
except requests.RequestException as exc:
|
|
246
243
|
_retry_network_error(method, path, attempt, total, backoffs, exc)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* Repository-local GitHub deployment receipts; never a store credential or transport. */
|
|
2
2
|
'use strict';
|
|
3
3
|
const https = require('node:https');
|
|
4
|
+
const {randomUUID} = require('node:crypto');
|
|
5
|
+
const {setTimeout: delay} = require('node:timers/promises');
|
|
4
6
|
|
|
5
7
|
function request(method, path, body, timeoutMs = 30000) {
|
|
6
8
|
const repo = process.env.GITHUB_REPOSITORY;
|
|
@@ -29,10 +31,43 @@ function request(method, path, body, timeoutMs = 30000) {
|
|
|
29
31
|
});
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
function uncertain(error) {
|
|
35
|
+
return /^mobile_release_(http_5\d\d|receipt_(read_unavailable|invalid|transport_unconfirmed|unconfirmed))$/
|
|
36
|
+
.test(error.message);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function confirmed(result, expected) {
|
|
40
|
+
return Number.isSafeInteger(result?.id) && result.id > 0 && result.state === expected.state &&
|
|
41
|
+
result.description === expected.description && result.log_url === expected.log_url;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function readStatus(id, expected) {
|
|
45
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
46
|
+
if (attempt) await delay(attempt * 1000);
|
|
47
|
+
try {
|
|
48
|
+
const rows = await request('GET', `/deployments/${id}/statuses?per_page=1`, undefined, 10000);
|
|
49
|
+
if (Array.isArray(rows) && confirmed(rows[0], expected)) return rows[0];
|
|
50
|
+
} catch (error) {
|
|
51
|
+
if (!uncertain(error)) break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
32
57
|
async function status(id, phase, state = 'in_progress') {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
58
|
+
const run = `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
|
|
59
|
+
const expected = {state, description: phase, auto_inactive: false,
|
|
60
|
+
log_url: `${run}/attempts/${process.env.GITHUB_RUN_ATTEMPT}#mobile-receipt-${randomUUID()}`};
|
|
61
|
+
try {
|
|
62
|
+
const result = await request('POST', `/deployments/${id}/statuses`, expected);
|
|
63
|
+
if (!confirmed(result, expected)) throw Error('mobile_release_receipt_unconfirmed');
|
|
64
|
+
return result;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (!uncertain(error)) throw error;
|
|
67
|
+
// Reconcile this invocation's one write. Never replay the POST or infer an upload from another receipt.
|
|
68
|
+
const result = await readStatus(id, expected);
|
|
69
|
+
if (result) return result;
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
37
72
|
}
|
|
38
73
|
module.exports = {request, status};
|
|
@@ -66,7 +66,7 @@ def unchanged(snapshot: dict[Path, str]) -> None:
|
|
|
66
66
|
raise guard.Refused("native_bundle_inputs_changed")
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
def prepare(root: Path, folder: Path,
|
|
69
|
+
def prepare(root: Path, folder: Path, log) -> tuple[list[str], dict[Path, str]]:
|
|
70
70
|
gemfile = next((p for p in (folder / "Gemfile", root / "Gemfile") if p.exists() or p.is_symlink()), None)
|
|
71
71
|
if gemfile is None:
|
|
72
72
|
return [], {}
|
|
@@ -74,7 +74,7 @@ def prepare(root: Path, folder: Path, proxy_helper: Path, log) -> tuple[list[str
|
|
|
74
74
|
gemfile.with_name("Gemfile.lock"): committed(root, gemfile.with_name("Gemfile.lock"), "gemfile_lock")}
|
|
75
75
|
prefix = ["/usr/bin/env", "BUNDLE_GEMFILE=" + str(gemfile), "BUNDLE_FROZEN=true",
|
|
76
76
|
"BUNDLE_PATH=" + (os.environ.get("BUNDLE_PATH") or str(root / ".factory/toolchain/gems"))]
|
|
77
|
-
relay = [
|
|
77
|
+
relay = [*prefix, "bundle"]
|
|
78
78
|
if command([*relay, "check"], gemfile.parent, log):
|
|
79
79
|
if command([*relay, "install", "--jobs", "2", "--retry", "1"], gemfile.parent, log):
|
|
80
80
|
refuse("native_bundle_install_failed", log, guard.Refused)
|
|
@@ -82,10 +82,9 @@ def prepare(root: Path, folder: Path, proxy_helper: Path, log) -> tuple[list[str
|
|
|
82
82
|
return [*prefix, "bundle", "exec"], snapshot
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
def run(root: Path, folder: Path,
|
|
85
|
+
def run(root: Path, folder: Path, argv: list[str]) -> dict:
|
|
86
86
|
root = root.resolve(strict=True)
|
|
87
87
|
folder = (root / folder).resolve(strict=True)
|
|
88
|
-
proxy_helper = proxy_helper.resolve(strict=True)
|
|
89
88
|
if not folder.is_relative_to(root) or not argv:
|
|
90
89
|
raise guard.Refused("native_bundle_path_unverified")
|
|
91
90
|
if (folder / "Podfile").is_symlink():
|
|
@@ -93,10 +92,8 @@ def run(root: Path, folder: Path, proxy_helper: Path, argv: list[str]) -> dict:
|
|
|
93
92
|
pod_lock = folder / "Podfile.lock"
|
|
94
93
|
pod_snapshot = {pod_lock: committed(root, pod_lock, "podfile_lock")} if (folder / "Podfile").exists() else {}
|
|
95
94
|
with tempfile.TemporaryFile() as log:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
prefix, snapshot = prepare(root, folder, proxy_helper, log)
|
|
99
|
-
if command([sys.executable, str(proxy_helper), "--", *prefix, *argv], root, log):
|
|
95
|
+
prefix, snapshot = prepare(root, folder, log)
|
|
96
|
+
if command([*prefix, *argv], root, log):
|
|
100
97
|
refuse("native_configuration_failed", log, guard.Refused)
|
|
101
98
|
unchanged(snapshot)
|
|
102
99
|
for path, digest in pod_snapshot.items():
|
|
@@ -114,12 +111,11 @@ def main(argv: list[str]) -> int:
|
|
|
114
111
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
115
112
|
parser.add_argument("--root", type=Path, default=Path.cwd())
|
|
116
113
|
parser.add_argument("--folder", type=Path, default=Path("ios"))
|
|
117
|
-
parser.add_argument("--proxy-helper", type=Path, required=True)
|
|
118
114
|
parser.add_argument("command", nargs=argparse.REMAINDER)
|
|
119
115
|
args = parser.parse_args(argv)
|
|
120
116
|
command_args = args.command[1:] if args.command[:1] == ["--"] else args.command
|
|
121
117
|
try:
|
|
122
|
-
answer = run(args.root, args.folder,
|
|
118
|
+
answer = run(args.root, args.folder, command_args)
|
|
123
119
|
except (guard.Refused, OSError, subprocess.SubprocessError) as exc:
|
|
124
120
|
code = str(exc) if isinstance(exc, guard.Refused) else "native_bundle_operation_unverified"
|
|
125
121
|
answer = {"ok": False, "code": code, "next": remediation(code)}
|
|
@@ -9,8 +9,8 @@ import sys
|
|
|
9
9
|
|
|
10
10
|
from native_project_graph import Refused, project, selected, workspace
|
|
11
11
|
|
|
12
|
-
REMEDIATION = ("Preserve source; use the vendor's official CocoaPods distribution
|
|
13
|
-
"
|
|
12
|
+
REMEDIATION = ("Preserve source; use the vendor's official CocoaPods distribution and commit "
|
|
13
|
+
"Podfile.lock, or verified local XCFrameworks; rerun the same task's build.")
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def check(root: Path, container: str = "", *, before_pods: bool = False, initial_pods_lock: bool = False) -> dict:
|
|
@@ -30,7 +30,7 @@ def committed(root: Path, lock: Path) -> str:
|
|
|
30
30
|
return hashlib.sha256(result.stdout).hexdigest()
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def prepare(root: Path, container: str
|
|
33
|
+
def prepare(root: Path, container: str) -> dict:
|
|
34
34
|
root = root.resolve(strict=True)
|
|
35
35
|
folder = (root / container).parent.resolve(strict=True) if container else root
|
|
36
36
|
if not folder.is_relative_to(root):
|
|
@@ -40,22 +40,17 @@ def prepare(root: Path, container: str, proxy_helper: Path) -> dict:
|
|
|
40
40
|
if (folder / "Podfile").is_symlink():
|
|
41
41
|
raise guard.Refused("native_workspace_reference_unverified")
|
|
42
42
|
digest = committed(root, folder / "Podfile.lock")
|
|
43
|
-
if not proxy_helper.is_file():
|
|
44
|
-
raise guard.Refused("native_google_transport_helper_required")
|
|
45
|
-
proxy_helper = proxy_helper.resolve(strict=True)
|
|
46
43
|
with tempfile.TemporaryFile() as log:
|
|
47
|
-
if command([sys.executable, str(proxy_helper)], root, log):
|
|
48
|
-
raise guard.Refused("native_google_proxy_required")
|
|
49
44
|
if not list(folder.glob("*.xcodeproj")) and (folder / "project.yml").is_file():
|
|
50
45
|
if command(["xcodegen", "generate"], folder, log):
|
|
51
46
|
refuse("native_project_generation_failed", log, guard.Refused)
|
|
52
47
|
initial = container or str(guard.selected(root, "", True).relative_to(root))
|
|
53
48
|
guard.check(root, initial, before_pods=True)
|
|
54
|
-
prefix, bundle_snapshot = native_bundle.prepare(root, folder,
|
|
49
|
+
prefix, bundle_snapshot = native_bundle.prepare(root, folder, log)
|
|
55
50
|
snapshot = {**bundle_snapshot, folder / "Podfile.lock": digest,
|
|
56
51
|
folder / "Podfile": hashlib.sha256((folder / "Podfile").read_bytes()).hexdigest()}
|
|
57
52
|
code, attempts = native_pods_retry.install(
|
|
58
|
-
[
|
|
53
|
+
[*prefix, "pod", "install", "--deployment", "--no-repo-update"],
|
|
59
54
|
folder, log, snapshot)
|
|
60
55
|
if code:
|
|
61
56
|
refuse("native_pods_install_failed", log, guard.Refused)
|
|
@@ -81,10 +76,9 @@ def main(argv: list[str]) -> int:
|
|
|
81
76
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
82
77
|
parser.add_argument("root", type=Path)
|
|
83
78
|
parser.add_argument("--container", default="")
|
|
84
|
-
parser.add_argument("--proxy-helper", type=Path, required=True)
|
|
85
79
|
args = parser.parse_args(argv)
|
|
86
80
|
try:
|
|
87
|
-
answer = prepare(args.root, args.container
|
|
81
|
+
answer = prepare(args.root, args.container)
|
|
88
82
|
except (guard.Refused, OSError, subprocess.SubprocessError) as exc:
|
|
89
83
|
code = str(exc) if isinstance(exc, guard.Refused) else "native_pods_operation_unverified"
|
|
90
84
|
answer = {"ok": False, "code": code, "next": guard.REMEDIATION}
|