gowalk-cicd 1.0.114 → 1.0.116
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 +2 -0
- package/action/.daemux-version +1 -1
- package/action/scripts/native_pods_diagnostics.py +15 -1
- package/action/scripts/test_native_pods_diagnostics.py +27 -0
- package/android-action/.daemux-version +1 -1
- package/backend-action/.daemux-version +1 -1
- package/package.json +1 -1
- package/templates/deploy.yml +11 -1
package/CLAUDE.md
CHANGED
|
@@ -216,6 +216,8 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
216
216
|
signals. Unknown signals remain unclassified; never copy child output or commands into annotations.
|
|
217
217
|
Timeout and cancellation retain the existing bounded sanitized diagnostic after owned-child cleanup;
|
|
218
218
|
preserve the failure code, install deadline and retry fences.
|
|
219
|
+
Within the bounded capture, retain the CocoaPods primary exception alongside the tail when a long
|
|
220
|
+
stack or secondary issue-search failure hides it. Redact before selecting the bounded excerpt.
|
|
219
221
|
- The mobile workflow's feature-branch-only `backend-preview` job bootstraps a
|
|
220
222
|
new app before GitHub registers `deploy-backend.yml` on the default branch.
|
|
221
223
|
Default-branch deploys continue through the separate backend workflow.
|
package/action/.daemux-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.116
|
|
@@ -23,6 +23,20 @@ def values(environment: dict[str, str]) -> set[str]:
|
|
|
23
23
|
return {value for value in found if value}
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def excerpt(text: str) -> str:
|
|
27
|
+
lines = text.splitlines()
|
|
28
|
+
tail = "\n".join(lines[-30:])[-4000:]
|
|
29
|
+
start = next((index for index in range(len(lines) - 1, -1, -1)
|
|
30
|
+
if lines[index].strip() == "### Error"), None)
|
|
31
|
+
if start is None:
|
|
32
|
+
return tail
|
|
33
|
+
primary = "\n".join(lines[start:start + 6])[:1200]
|
|
34
|
+
if primary in tail:
|
|
35
|
+
return tail
|
|
36
|
+
tail = "\n".join(lines[-(29 - len(primary.splitlines())):])[-(3995 - len(primary)):]
|
|
37
|
+
return primary + "\n...\n" + tail
|
|
38
|
+
|
|
39
|
+
|
|
26
40
|
def diagnostic(log, environment: dict[str, str] | None = None) -> str:
|
|
27
41
|
log.flush()
|
|
28
42
|
log.seek(0, os.SEEK_END)
|
|
@@ -44,7 +58,7 @@ def diagnostic(log, environment: dict[str, str] | None = None) -> str:
|
|
|
44
58
|
text = re.sub(r"\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+", "[token redacted]", text)
|
|
45
59
|
text = re.sub(r"https?://[^\s\"'<>]+", "[URL redacted]", text)
|
|
46
60
|
text = re.sub(r"[A-Za-z0-9_+/=-]{32,}", "[long value redacted]", text)
|
|
47
|
-
return
|
|
61
|
+
return excerpt(text)
|
|
48
62
|
|
|
49
63
|
|
|
50
64
|
def refuse(code: str, log, exception):
|
|
@@ -37,3 +37,30 @@ class DiagnosticsTests(unittest.TestCase):
|
|
|
37
37
|
self.assertLessEqual(len(result.splitlines()), 30)
|
|
38
38
|
pem = b"-----BEGIN PRIVATE KEY-----\nPRIVATE_PEM_VALUE\n-----END PRIVATE KEY-----\n"
|
|
39
39
|
self.assertNotIn("PRIVATE_PEM_VALUE", diagnostic(io.BytesIO(pem), {}))
|
|
40
|
+
|
|
41
|
+
def test_cocoapods_primary_exception_survives_long_stack_and_secondary_failure(self):
|
|
42
|
+
body = ('Analyzing dependencies\n### Error\n\n```\n'
|
|
43
|
+
'FixturePodError - cannot install dependency 12.3\n'
|
|
44
|
+
'Authorization: Bearer fixture-private-value\n'
|
|
45
|
+
'https://fixture-user:fixture-password@example.invalid/private\n')
|
|
46
|
+
body += ''.join(f'/ruby/gems/example/file_{index}.rb:12:in helper_{index}\n' for index in range(80))
|
|
47
|
+
body += '```\nTEMPLATE END\nSearching for inspections failed: secondary query refused\n'
|
|
48
|
+
result = diagnostic(io.BytesIO(body.encode()), {})
|
|
49
|
+
self.assertIn('FixturePodError - cannot install dependency 12.3', result)
|
|
50
|
+
self.assertIn('secondary query refused', result)
|
|
51
|
+
self.assertNotIn('fixture-private-value', result)
|
|
52
|
+
self.assertNotIn('fixture-password', result)
|
|
53
|
+
self.assertNotIn('example.invalid', result)
|
|
54
|
+
self.assertLessEqual(len(result), 4000)
|
|
55
|
+
self.assertLessEqual(len(result.splitlines()), 30)
|
|
56
|
+
self.assertEqual(diagnostic(io.BytesIO(result.encode()), {}), result)
|
|
57
|
+
|
|
58
|
+
def test_primary_exception_survives_character_bound_as_well_as_line_bound(self):
|
|
59
|
+
body = '### Error\n\n```\nFixturePodError - initial failure\n'
|
|
60
|
+
body += ('frame with many ordinary path components ' * 8 + '\n') * 28
|
|
61
|
+
body += 'secondary cleanup failure\n'
|
|
62
|
+
result = diagnostic(io.BytesIO(body.encode()), {})
|
|
63
|
+
self.assertIn('FixturePodError - initial failure', result)
|
|
64
|
+
self.assertIn('secondary cleanup failure', result)
|
|
65
|
+
self.assertLessEqual(len(result), 4000)
|
|
66
|
+
self.assertLessEqual(len(result.splitlines()), 30)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.116
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.116
|
package/package.json
CHANGED
package/templates/deploy.yml
CHANGED
|
@@ -581,9 +581,19 @@ jobs:
|
|
|
581
581
|
run: |
|
|
582
582
|
echo "::notice title=play_review_pending::{\"schema\":\"gowalk-cicd/play-review-pending.v1\",\"package\":\"${PACKAGE}\",\"track\":\"${TRACK}\",\"version_code\":\"${VERSION_CODE}\"}"
|
|
583
583
|
|
|
584
|
+
# Saved even when the build failed OR the job ran out of time. The cache
|
|
585
|
+
# holds DOWNLOADS, not build outputs: Gradle's `modules-2` store is
|
|
586
|
+
# content-addressed and re-verified on use, and a partial fetch never
|
|
587
|
+
# enters it. `!cancelled()` still skipped exactly the case that matters —
|
|
588
|
+
# a job cancelled at its own `timeout-minutes` — which deadlocked every
|
|
589
|
+
# app's FIRST Android release: a cold build that exceeds the cap is
|
|
590
|
+
# cancelled before this step, so nothing is cached, so the next attempt is
|
|
591
|
+
# cold too. Foundy (2026-09-09) spent 39 of its 45 minutes in
|
|
592
|
+
# `flutter_bundle` with no cache entry for the repository at all, while an
|
|
593
|
+
# app with a warm cache finishes the same job in 13 minutes.
|
|
584
594
|
- name: Save Gradle dependencies
|
|
585
595
|
if: >-
|
|
586
|
-
${{
|
|
596
|
+
${{ always() && steps.mode.outputs.mode == 'local'
|
|
587
597
|
&& steps.gradle_cache.outputs.cache-primary-key != ''
|
|
588
598
|
&& steps.gradle_cache.outputs.cache-hit != 'true' }}
|
|
589
599
|
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25
|