gowalk-cicd 1.0.33 → 1.0.35

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/README.md CHANGED
@@ -184,11 +184,11 @@ sent for review from the Google Play Console UI.
184
184
  ```
185
185
 
186
186
  That fails the whole upload, so the bundle you just built never reaches Play at
187
- all. The retry re-uploads with `changesNotSentForReview`, which lands the bundle
188
- and leaves it waiting, then emits a `::warning::` naming the package. Someone
189
- then presses **Send changes for review** on that app's Publishing overview page.
190
- There is no API for that press it is the one step Google deliberately reserves
191
- for a human, and no amount of tooling removes it.
187
+ all. After an ordinary fresh-edit retry, the final retry re-uploads with
188
+ `changesNotSentForReview`, which lands the bundle and leaves it waiting, then
189
+ emits a `::warning::` naming the package. The delivery system can then complete
190
+ the console-only **Send changes for review** action through the app's leased
191
+ AdsPower profile.
192
192
 
193
193
  In the ordinary case the first upload submits normally and the retry is skipped.
194
194
 
@@ -204,8 +204,10 @@ long enough outlives one:
204
204
 
205
205
  Neither says anything about the build, which is signed and retained by that
206
206
  point. The upload step therefore runs with `continue-on-error` and a second
207
- attempt follows when the first fails a fresh edit succeeds. Both attempts
208
- failing still fails the job.
207
+ ordinary attempt follows when the first fails. This preserves automatic review
208
+ submission while opening a fresh edit. Only when that retry also fails does a
209
+ third attempt use `changesNotSentForReview`; setting that flag on an ordinary
210
+ app is itself a Play validation error.
209
211
 
210
212
  One caveat this makes explicit: **nothing else should hold an edit open on the
211
213
  same package while a deploy runs.** A script that polls `edits.insert` /
@@ -437,6 +439,13 @@ The iOS composite action runs on `macos-15` and:
437
439
 
438
440
  The iOS action requires only the p8. Everything else is derived.
439
441
 
442
+ Feature-branch runs installed from the standard workflow still archive and
443
+ upload to TestFlight, but pass `manage-app-store-version: 'false'`. This keeps
444
+ branch validation independent of the editable App Store release slot, so a
445
+ build can upload while the current release is locked in review. Default-branch
446
+ runs retain version creation and metadata automation. Direct action callers
447
+ keep the historical behavior because the new input defaults to `true`.
448
+
440
449
  ### App ID capabilities
441
450
 
442
451
  A provisioning profile carries only the capabilities enabled on its App ID.
@@ -570,6 +579,7 @@ common ones:
570
579
  | `uses-non-exempt-encryption` | Value for `ITSAppUsesNonExemptEncryption` |
571
580
  | `archive` | `false` to build-only (PR runs without secrets) |
572
581
  | `upload` | `false` to archive but not upload to TestFlight |
582
+ | `manage-app-store-version` | `false` to upload without creating/editing the App Store release slot |
573
583
  | `app-store-whats-new` | Inline "What's New" text (overrides files) |
574
584
  | `ai-metadata` | `false` to disable AI auto-fill of empty ASC metadata |
575
585
  | `ai-metadata-model` | GitHub Models model id (default `openai/gpt-4o`) |
@@ -1 +1 @@
1
- 1.0.33
1
+ 1.0.35
package/action/action.yml CHANGED
@@ -71,6 +71,13 @@ inputs:
71
71
  secrets. When 'false', `upload` is ignored.
72
72
  required: false
73
73
  default: "true"
74
+ manage-app-store-version:
75
+ description: >
76
+ Set to 'false' to archive and upload a TestFlight build without creating
77
+ or editing an App Store version. App Store metadata automation is skipped.
78
+ This is useful for feature-branch validation while a release is in review.
79
+ required: false
80
+ default: "true"
74
81
  run-tests:
75
82
  description: "Set to 'false' to skip the simulator test stage"
76
83
  required: false
@@ -289,7 +296,7 @@ runs:
289
296
  | tee -a "$GITHUB_ENV"
290
297
 
291
298
  - name: Resolve App Store version slot (REUSE or CREATE)
292
- if: ${{ inputs.archive == 'true' }}
299
+ if: ${{ inputs.archive == 'true' && inputs.manage-app-store-version == 'true' }}
293
300
  shell: bash
294
301
  env:
295
302
  APP_STORE_APPLE_ID: ${{ inputs.app-store-apple-id || env.CFG_APP_STORE_APPLE_ID }}
@@ -335,6 +342,18 @@ runs:
335
342
  echo "APP_STORE_VERSION_ID=$APP_STORE_VERSION_ID" >> "$GITHUB_ENV"
336
343
  echo "Using marketing version $MARKETING_VERSION build $BUILD_NUMBER (decision=$DECISION_JSON)"
337
344
 
345
+ - name: Resolve TestFlight build number
346
+ if: ${{ inputs.archive == 'true' && inputs.manage-app-store-version == 'false' }}
347
+ shell: bash
348
+ env:
349
+ APP_STORE_APPLE_ID: ${{ inputs.app-store-apple-id || env.CFG_APP_STORE_APPLE_ID }}
350
+ run: |
351
+ set -o pipefail
352
+ BUILD_NUMBER=$(python3 "${{ github.action_path }}/scripts/next_build_number.py")
353
+ echo "BUILD_NUMBER=$BUILD_NUMBER" >> "$GITHUB_ENV"
354
+ echo "APP_STORE_VERSION_ID=" >> "$GITHUB_ENV"
355
+ echo "Using marketing version $MARKETING_VERSION build $BUILD_NUMBER without an App Store version slot"
356
+
338
357
  - name: Notice on deprecated profile-name input
339
358
  if: ${{ inputs.archive == 'true' && inputs.profile-name != '' }}
340
359
  shell: bash
@@ -714,7 +733,9 @@ runs:
714
733
 
715
734
  - name: Detect empty ASC metadata fields
716
735
  id: detect_metadata
717
- if: ${{ inputs.archive == 'true' && inputs.upload == 'true' && inputs.ai-metadata != 'false' }}
736
+ if: >-
737
+ ${{ inputs.archive == 'true' && inputs.upload == 'true'
738
+ && inputs.manage-app-store-version == 'true' && inputs.ai-metadata != 'false' }}
718
739
  shell: bash
719
740
  env:
720
741
  APP_STORE_APPLE_ID: ${{ inputs.app-store-apple-id || env.CFG_APP_STORE_APPLE_ID }}
@@ -969,6 +990,7 @@ runs:
969
990
  # with the default (CFG_WHATS_NEW), preserving any AI-generated notes.
970
991
  - name: Set App Store "What's New"
971
992
  if: ${{ inputs.archive == 'true' && inputs.upload == 'true'
993
+ && inputs.manage-app-store-version == 'true'
972
994
  && (inputs.app-store-whats-new != '' || env.CFG_WHATS_NEW != '') }}
973
995
  shell: bash
974
996
  env:
@@ -0,0 +1,50 @@
1
+ import re
2
+ import unittest
3
+ from pathlib import Path
4
+
5
+
6
+ ACTION_YAML = Path(__file__).resolve().parents[1] / "action.yml"
7
+
8
+
9
+ def step_block(source: str, name: str) -> str:
10
+ pattern = rf" - name: {re.escape(name)}\n(?P<body>.*?)(?=\n - name:|\Z)"
11
+ match = re.search(pattern, source, re.DOTALL)
12
+ if match is None:
13
+ raise AssertionError(f"missing action step: {name}")
14
+ return match.group("body")
15
+
16
+
17
+ class TestTestFlightVersionSlotWiring(unittest.TestCase):
18
+ @classmethod
19
+ def setUpClass(cls) -> None:
20
+ cls.source = ACTION_YAML.read_text(encoding="utf-8")
21
+
22
+ def test_opt_out_is_backward_compatible(self) -> None:
23
+ self.assertRegex(
24
+ self.source,
25
+ r"(?m)^ manage-app-store-version:\n(?: .*\n)*? default: \"true\"$",
26
+ )
27
+
28
+ def test_opt_out_skips_store_version_but_keeps_build_number(self) -> None:
29
+ store_slot = step_block(self.source, "Resolve App Store version slot (REUSE or CREATE)")
30
+ testflight = step_block(self.source, "Resolve TestFlight build number")
31
+
32
+ self.assertIn("inputs.manage-app-store-version == 'true'", store_slot)
33
+ self.assertIn("inputs.manage-app-store-version == 'false'", testflight)
34
+ self.assertIn(
35
+ "APP_STORE_APPLE_ID: ${{ inputs.app-store-apple-id || env.CFG_APP_STORE_APPLE_ID }}",
36
+ testflight,
37
+ )
38
+ self.assertIn("next_build_number.py", testflight)
39
+ self.assertNotIn("manage_marketing_version.py", testflight)
40
+
41
+ def test_metadata_requires_a_managed_store_version(self) -> None:
42
+ detector = step_block(self.source, "Detect empty ASC metadata fields")
43
+ whats_new = step_block(self.source, 'Set App Store "What\'s New"')
44
+
45
+ self.assertIn("inputs.manage-app-store-version == 'true'", detector)
46
+ self.assertIn("inputs.manage-app-store-version == 'true'", whats_new)
47
+
48
+
49
+ if __name__ == "__main__":
50
+ unittest.main()
@@ -1 +1 @@
1
- 1.0.33
1
+ 1.0.35
@@ -1 +1 @@
1
- 1.0.33
1
+ 1.0.35
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gowalk-cicd",
3
- "version": "1.0.33",
3
+ "version": "1.0.35",
4
4
  "description": "Zero-config GitHub Actions delivery for iOS TestFlight and Android Google Play.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -113,6 +113,11 @@ jobs:
113
113
  workspace: ${{ steps.flutter.outputs.enabled == 'true' && 'ios/Runner.xcworkspace' || '' }}
114
114
  scheme: ${{ steps.flutter.outputs.enabled == 'true' && 'Runner' || '' }}
115
115
  run-tests: 'false' # tests belong to the CI gate, not the deploy path
116
+ # A feature-branch TestFlight build must not create or mutate a live
117
+ # App Store version. That also lets it upload while the current version
118
+ # is locked in review. Default-branch deploys retain metadata automation.
119
+ manage-app-store-version: >-
120
+ ${{ github.ref_name == github.event.repository.default_branch && 'true' || 'false' }}
116
121
 
117
122
  android:
118
123
  name: Android Google Play
@@ -358,20 +363,40 @@ jobs:
358
363
  ${{ vars.GOOGLE_PLAY_STATUS == 'inProgress' && (vars.GOOGLE_PLAY_USER_FRACTION || '0.2') || '' }}
359
364
  whatsNewDirectory: ${{ hashFiles('distribution/whatsnew/**') != '' && 'distribution/whatsnew' || '' }}
360
365
 
361
- # The retry serves two different failures, and both need a fresh edit:
362
- # * the edit expired mid-upload (a large bundle on a slow runner), and
363
- # * Play refused to auto-submit: "Changes cannot be sent for review
364
- # automatically. Please set changesNotSentForReview to true." Play returns
365
- # this once an app has changes a human must submit — after a policy
366
- # rejection, for instance — and it fails the whole upload, so the built
367
- # bundle never lands at all.
368
- - name: Retry Google Play upload without auto-submit
369
- id: play-upload-retry
366
+ # A failed action does not expose a machine-readable Play error code. Retry once
367
+ # with the ordinary review mode first: that opens a fresh edit and repairs an edit
368
+ # that expired during a slow upload without changing submission semantics.
369
+ - name: Retry Google Play upload with a fresh edit
370
+ id: play-upload-fresh-retry
371
+ continue-on-error: true
370
372
  if: >-
371
373
  ${{ steps.mode.outputs.mode == 'local'
372
374
  && steps.play.outputs.ready == 'true'
373
375
  && steps.play-upload.outcome == 'failure' }}
374
376
  uses: r0adkll/upload-google-play@e738b9dd8f2476ea806d921b64aacd24f34515a5 # v1.1.5
377
+ with:
378
+ serviceAccountJson: ${{ steps.android.outputs.play-service-account }}
379
+ packageName: ${{ steps.android.outputs.package-name }}
380
+ releaseFiles: ${{ steps.android.outputs.bundle-path }}
381
+ tracks: ${{ vars.GOOGLE_PLAY_TRACK || 'internal' }}
382
+ status: ${{ vars.GOOGLE_PLAY_STATUS || 'completed' }}
383
+ userFraction: >-
384
+ ${{ vars.GOOGLE_PLAY_STATUS == 'inProgress' && (vars.GOOGLE_PLAY_USER_FRACTION || '0.2') || '' }}
385
+ whatsNewDirectory: >-
386
+ ${{ hashFiles('distribution/whatsnew/**') != '' && 'distribution/whatsnew' || '' }}
387
+
388
+ # If the ordinary fresh-edit retry also fails, Play may be requiring the
389
+ # changesNotSentForReview mode used after a policy rejection. A third, fresh edit
390
+ # is intentionally reserved for that case. Setting the flag on the edit-expiry
391
+ # retry is invalid for apps whose changes are submitted automatically.
392
+ - name: Retry Google Play upload without auto-submit
393
+ id: play-upload-review-retry
394
+ if: >-
395
+ ${{ steps.mode.outputs.mode == 'local'
396
+ && steps.play.outputs.ready == 'true'
397
+ && steps.play-upload.outcome == 'failure'
398
+ && steps.play-upload-fresh-retry.outcome == 'failure' }}
399
+ uses: r0adkll/upload-google-play@e738b9dd8f2476ea806d921b64aacd24f34515a5 # v1.1.5
375
400
  with:
376
401
  serviceAccountJson: ${{ steps.android.outputs.play-service-account }}
377
402
  packageName: ${{ steps.android.outputs.package-name }}
@@ -385,7 +410,7 @@ jobs:
385
410
  changesNotSentForReview: true
386
411
 
387
412
  - name: Say what still needs a human
388
- if: ${{ always() && steps.play-upload-retry.outcome == 'success' }}
413
+ if: ${{ always() && steps.play-upload-review-retry.outcome == 'success' }}
389
414
  shell: bash
390
415
  run: |
391
416
  echo "::warning::Play would not accept this release for review automatically, so it was \