gowalk-cicd 1.0.145 → 1.0.146

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.
Files changed (69) hide show
  1. package/CLAUDE.md +39 -61
  2. package/README.md +28 -42
  3. package/action/.daemux-version +1 -1
  4. package/action/action.yml +0 -9
  5. package/action/scripts/asc_common.py +4 -7
  6. package/action/scripts/native_bundle.py +6 -10
  7. package/action/scripts/native_dependency_guard.py +2 -2
  8. package/action/scripts/native_pods.py +4 -10
  9. package/action/scripts/test_asc_common_timeouts.py +0 -1
  10. package/action/scripts/test_asc_network_diagnostics.py +10 -21
  11. package/action/scripts/test_flutter_native_preparation.py +1 -5
  12. package/action/scripts/test_native_bundle.py +4 -11
  13. package/action/scripts/test_native_dependency_wiring.py +5 -3
  14. package/action/scripts/test_native_pods.py +13 -34
  15. package/action/scripts/test_native_pods_diagnostics.py +1 -1
  16. package/action/scripts/test_native_pods_retry.py +2 -8
  17. package/action/scripts/test_native_prepare_evidence.py +3 -3
  18. package/action/scripts/test_upload_build.py +7 -15
  19. package/action/scripts/upload_build.py +12 -8
  20. package/android-action/.daemux-version +1 -1
  21. package/android-action/action.yml +8 -32
  22. package/android-action/flutter-setup/action.yml +1 -2
  23. package/android-action/play-upload/process.cjs +1 -12
  24. package/android-action/play-upload/run.cjs +2 -2
  25. package/android-action/scripts/crashlytics_bootstrap.py +2 -2
  26. package/android-action/scripts/crashlytics_bootstrap_test_support.py +54 -27
  27. package/android-action/scripts/crashlytics_symbols.py +5 -3
  28. package/android-action/scripts/flutter_manifest.py +1 -3
  29. package/android-action/scripts/flutter_manifest_fixture.py +58 -1
  30. package/android-action/scripts/play_inventory.py +3 -3
  31. package/android-action/scripts/play_preflight.py +2 -2
  32. package/android-action/scripts/test_android_build_diagnostics.py +5 -8
  33. package/android-action/scripts/test_crashlytics_bootstrap.py +7 -29
  34. package/android-action/scripts/test_crashlytics_symbols.py +1 -2
  35. package/android-action/scripts/test_flutter_archive.py +23 -25
  36. package/android-action/scripts/test_flutter_archive_cache.py +7 -25
  37. package/android-action/scripts/test_flutter_archive_setup.py +5 -6
  38. package/android-action/scripts/test_flutter_archive_size.py +3 -3
  39. package/android-action/scripts/test_flutter_cache_setup.py +7 -24
  40. package/android-action/scripts/test_flutter_manifest.py +20 -39
  41. package/android-action/scripts/test_flutter_manifest_scope.py +8 -6
  42. package/android-action/scripts/test_flutter_origin_retry.py +66 -0
  43. package/android-action/scripts/test_flutter_release_cache.py +13 -22
  44. package/android-action/scripts/test_play_inventory.py +1 -1
  45. package/android-action/scripts/test_play_preflight.py +0 -8
  46. package/backend-action/.daemux-version +1 -1
  47. package/package.json +1 -1
  48. package/src/config/build-steps.mjs +7 -3
  49. package/templates/deploy-web.yml +1 -4
  50. package/templates/deploy.yml +4 -11
  51. package/templates/history.json.gz +0 -0
  52. package/action/scripts/apple_store_proxy.py +0 -28
  53. package/action/scripts/test_apple_store_proxy.py +0 -44
  54. package/android-action/scripts/jvm_proxy_relay.py +0 -166
  55. package/android-action/scripts/play_proxy_test_support.py +0 -82
  56. package/android-action/scripts/play_store_proxy.py +0 -109
  57. package/android-action/scripts/test_crashlytics_symbols_proxy.py +0 -54
  58. package/android-action/scripts/test_flutter_proxy_retry.py +0 -83
  59. package/android-action/scripts/test_flutter_test_loopback.py +0 -73
  60. package/android-action/scripts/test_google_bootstrap_proxy.py +0 -77
  61. package/android-action/scripts/test_google_bootstrap_wiring.py +0 -140
  62. package/android-action/scripts/test_jvm_proxy_cleanup.py +0 -44
  63. package/android-action/scripts/test_jvm_proxy_idle.py +0 -106
  64. package/android-action/scripts/test_jvm_proxy_loopback.py +0 -91
  65. package/android-action/scripts/test_jvm_proxy_relay.py +0 -148
  66. package/android-action/scripts/test_play_connect_runtime.py +0 -62
  67. package/android-action/scripts/test_play_preflight_proxy_runtime.py +0 -58
  68. package/android-action/scripts/test_play_store_proxy.py +0 -98
  69. 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. Set lower-case spellings
108
- or clear a lower-case bypass through `play_store_proxy.py -- <command>` (child
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
- - Every Apple/Google store API call, OAuth exchange and binary upload requires its
116
- assigned `APPLE_STORE_PROXY_URL` / `GOOGLE_STORE_PROXY_URL` repository secret.
117
- Python clients enforce explicit proxies; Play upload steps set the proxy for the
118
- pinned Google client. Missing configuration must stop before a provider call.
119
- Apple IPA uploads use `action/scripts/upload_build.py`, not native upload tools.
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. Every Gradle test/build and SDK download runs
147
- under `play_store_proxy.py --`, whose owned loopback relay gives Java an explicit
148
- authenticated account exit without credentials in JVM options. The child HTTP_PROXY
149
- and HTTPS_PROXY variables also name the credential-free loopback relay because
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 removing proxy variables in that cache process.
173
- Unknown code or origins refuse; SDK setup, non-cache children and later steps retain their
174
- proxy requirement. Never export this scope through `GITHUB_ENV` or add cache domains to
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 retains the account proxy and allows four attempts within 60 seconds for manifests or 20 minutes
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. Proxy CONNECT 502/503/504 share that retry budget even
183
- when curl exits 22 with origin status 0. Authentication/certificate refusals remain terminal.
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 and provider transport stay unchanged.
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, then removes inherited proxy
222
- variables only inside the official `upload-artifact` process. Unknown programs/origins refuse;
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` inside the
270
- existing proxy wrapper. It retains at most 64 KiB of private child output and publishes
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, proxy environment, signing and symbol checks.
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
- proxy environment variables do not protect SwiftPM downloads. The same app session preserves
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
- through the existing Google relay, then checks the completed workspace. No Podfile means no
288
- dependency download or Google proxy requirement. Initial local lock resolution may use the
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 through the same relay with a frozen bundle.
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 follows the Google account proxy. Android builds and
343
- the pinned Firebase CLI receive the explicit proxy environment; Crashlytics Gradle
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, using the configured proxy.
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 proxied GET recovery to three attempts within three minutes. Java receives
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 / CONNECT 502,503,504 evidence that no provider request was sent. Bare proxy errors,
365
- TLS verification failures, provider responses and lost origin responses do not authorize a retry.
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, proxy, track/status/rollout and notes survive one bounded retry;
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 and does not
428
- change the Google account proxy. Update workflow wiring as well as action directories.
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`.
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 through the assigned Google proxy; SDK setup errors still fail the
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`. In-progress notices arrive each minute; elapsed time belongs to
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 and the configured provider proxy; only a verified complete archive
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. Every request keeps the assigned
446
- Google proxy; an absent edit after cleanup is already closed. Exhausted recovery
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. Both proxy spellings
457
- and bypass variables are explicitly set for only that provider subprocess.
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 runs through an owned loopback relay to `GOOGLE_STORE_PROXY_URL`.
524
- The relay authenticates to that exit without putting credentials in JVM options;
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. Configure the account's `GOOGLE_STORE_PROXY_URL`
779
- repository secret before any provider operation.
772
+ as the `firebase-app-id` input.
780
773
 
781
- Android builds and the pinned Firebase CLI receive the proxy explicitly, including
782
- Crashlytics mapping/native-symbol uploads. Crashlytics Gradle 2.9.2+ supports proxy
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 through
787
- the assigned account proxy and verifies its exact size and SHA-256. Verified bytes are
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
- All Apple and Google store requests require an account-pinned proxy, including OAuth,
810
- metadata and binary transfer. Provision `APPLE_STORE_PROXY_URL` and
811
- `GOOGLE_STORE_PROXY_URL` as encrypted repository secrets before deployment. A missing
812
- proxy refuses provider calls; there is no direct fallback. Refresh existing workflow
813
- files with the released installer while preserving application-specific build inputs.
814
- The Google pin also covers Flutter SDK manifest/archive downloads and early `pub`
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 without inheriting the store proxy; unknown programs and destinations are
824
- refused. The scope ends with that Node process. Apple/Google calls retain their assigned
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. This fixes the proven
828
- inherited-proxy path; an isolated `ECONNRESET` does not identify every possible network fault.
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 through `APPLE_STORE_PROXY_URL`.
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` (`proxy_missing`, `ipa_invalid`,
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 on the assigned proxy, with four attempts
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
@@ -1 +1 @@
1
- 1.0.145
1
+ 1.0.146
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 proxy URLs."""
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 through the configured proxy (category={category})"
180
+ f"attempts (category={category})"
184
181
  )
185
182
  delay = backoffs[attempt]
186
183
  print(
187
- f"ASC {method} {path} network error through the configured proxy; "
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, proxies=proxies(),
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)
@@ -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, proxy_helper: Path, log) -> tuple[list[str], dict[Path, str]]:
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 = [sys.executable, str(proxy_helper), "--", *prefix, "bundle"]
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, proxy_helper: Path, argv: list[str]) -> dict:
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
- if command([sys.executable, str(proxy_helper)], root, log):
97
- raise guard.Refused("native_google_proxy_required")
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, args.proxy_helper, command_args)
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 through the assigned Google proxy "
13
- "and commit Podfile.lock, or verified local XCFrameworks; rerun the same task's build.")
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, proxy_helper: Path) -> dict:
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, proxy_helper, log)
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
- [sys.executable, str(proxy_helper), "--", *prefix, "pod", "install", "--deployment", "--no-repo-update"],
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, args.proxy_helper)
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}
@@ -38,7 +38,6 @@ class _OkResponse:
38
38
  return {"data": []}
39
39
 
40
40
 
41
- @mock.patch.dict(os.environ, {"APPLE_STORE_PROXY_URL": "http://proxy.test:1234"})
42
41
  class RequestTimeoutTests(unittest.TestCase):
43
42
  """``request()`` must pass an explicit ``(connect, read)`` timeout."""
44
43