gowalk-cicd 1.0.118 → 1.0.120
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/action/.daemux-version +1 -1
- package/action/scripts/mobile_release.cjs +12 -1
- package/action/scripts/native_pods_diagnostics.py +18 -1
- package/action/scripts/test_native_pods_diagnostics.py +20 -0
- package/android-action/.daemux-version +1 -1
- package/backend-action/.daemux-version +1 -1
- package/package.json +1 -1
package/action/.daemux-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.120
|
|
@@ -66,8 +66,19 @@ async function phase(action, platform) {
|
|
|
66
66
|
if (!id) return; // Existing consumers without release-intent wiring keep their original behavior.
|
|
67
67
|
const record = await api.request('GET', `/deployments/${id}`);
|
|
68
68
|
const expected = owner(platform, record.payload?.fingerprint);
|
|
69
|
+
// An EARLIER attempt of this same run owns the record legitimately. `admit`
|
|
70
|
+
// only re-runs when it failed, so "re-run failed jobs" — the ordinary way to
|
|
71
|
+
// recover a release that died in transport — leaves the record stamped with
|
|
72
|
+
// attempt 1 while the platform job runs as attempt 2. Demanding an exact
|
|
73
|
+
// match made that recovery impossible: obd-scanner's Android leg built for
|
|
74
|
+
// twenty-six minutes, then refused at the upload intent (2026-09-09).
|
|
75
|
+
// Upload-once does not rest on this number. It rests on the status check
|
|
76
|
+
// below, which admits `begin-upload` only from `building`; a record whose
|
|
77
|
+
// upload already began or finished is refused there, on any attempt.
|
|
78
|
+
const attempt = record.payload?.run_attempt;
|
|
69
79
|
if (record.payload?.schema !== SCHEMA || record.payload.run_id !== expected.run_id ||
|
|
70
|
-
|
|
80
|
+
!Number.isSafeInteger(attempt) || attempt > expected.run_attempt ||
|
|
81
|
+
record.sha !== expected.source_sha ||
|
|
71
82
|
record.payload.platform !== platform) throw Error('mobile_release_phase_owner_mismatch');
|
|
72
83
|
const statuses = await api.request('GET', `/deployments/${id}/statuses?per_page=1`);
|
|
73
84
|
const required = action === 'begin-upload' ? 'building' : 'uploading';
|
|
@@ -37,6 +37,23 @@ def excerpt(text: str) -> str:
|
|
|
37
37
|
return primary + "\n...\n" + tail
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
#: A long run that is a lowercase snake_case NAME rather than an opaque value.
|
|
41
|
+
#: Thirteen of this helper's own error codes are 32 characters or more —
|
|
42
|
+
#: `native_podfile_lock_commit_required` is 35, `native_google_transport_helper_required`
|
|
43
|
+
#: is 39 — so the catch-all below erased the one token the classifier reads back
|
|
44
|
+
#: out of this text: task 1185's iOS failure published `"code": "[long value
|
|
45
|
+
#: redacted]"` with an empty `signals` list, and every pods failure in the fleet
|
|
46
|
+
#: was diagnosed blind (2026-09-09). Requiring an underscore keeps hex digests and
|
|
47
|
+
#: base32/base64 material opaque, and every environment value has already been
|
|
48
|
+
#: replaced verbatim above.
|
|
49
|
+
_NAME_RUN = re.compile(r"[a-z]+(?:_[a-z0-9]+)+")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _opaque_run(match: "re.Match[str]") -> str:
|
|
53
|
+
run = match.group(0)
|
|
54
|
+
return run if _NAME_RUN.fullmatch(run) else "[long value redacted]"
|
|
55
|
+
|
|
56
|
+
|
|
40
57
|
def diagnostic(log, environment: dict[str, str] | None = None) -> str:
|
|
41
58
|
log.flush()
|
|
42
59
|
log.seek(0, os.SEEK_END)
|
|
@@ -57,7 +74,7 @@ def diagnostic(log, environment: dict[str, str] | None = None) -> str:
|
|
|
57
74
|
r'\1"[redacted]"', text)
|
|
58
75
|
text = re.sub(r"\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+", "[token redacted]", text)
|
|
59
76
|
text = re.sub(r"https?://[^\s\"'<>]+", "[URL redacted]", text)
|
|
60
|
-
text = re.sub(r"[A-Za-z0-9_+/=-]{32,}",
|
|
77
|
+
text = re.sub(r"[A-Za-z0-9_+/=-]{32,}", _opaque_run, text)
|
|
61
78
|
return excerpt(text)
|
|
62
79
|
|
|
63
80
|
|
|
@@ -23,6 +23,26 @@ class DiagnosticsTests(unittest.TestCase):
|
|
|
23
23
|
'cHJpdmF0ZTpwYXNzd29yZA==', 'PRIVATE_JSON_MARKER', 'PRIVATE_ACCESS_MARKER', 'SECRET'):
|
|
24
24
|
self.assertNotIn(private, result)
|
|
25
25
|
|
|
26
|
+
def test_error_codes_survive_while_opaque_runs_of_the_same_length_do_not(self):
|
|
27
|
+
"""The classifier reads the plugin's own code back out of this text, and
|
|
28
|
+
thirteen of the twenty-seven are 32 characters or more. Task 1185's iOS
|
|
29
|
+
failure published `"code": "[long value redacted]"` with an empty
|
|
30
|
+
`signals` list because the catch-all erased it (2026-09-09)."""
|
|
31
|
+
body = ('{"code": "native_podfile_lock_commit_required", "ok": false}\n'
|
|
32
|
+
'native_google_transport_helper_required native_pods_operation_unverified\n'
|
|
33
|
+
'digest 9f2b7c1e4a8d3b6f0c5e2a9d7b4f1c8e3a6d0b5f were removed\n'
|
|
34
|
+
'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQ==\n'
|
|
35
|
+
'a_secret_looking_run_of_lowercase_words_kept\n')
|
|
36
|
+
result = diagnostic(io.BytesIO(body.encode()), {})
|
|
37
|
+
for code in ('native_podfile_lock_commit_required', 'native_google_transport_helper_required',
|
|
38
|
+
'native_pods_operation_unverified'):
|
|
39
|
+
self.assertIn(code, result)
|
|
40
|
+
# A hex digest and base64 material carry no underscore and stay opaque.
|
|
41
|
+
for opaque in ('9f2b7c1e4a8d3b6f0c5e2a9d7b4f1c8e3a6d0b5f',
|
|
42
|
+
'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQ=='):
|
|
43
|
+
self.assertNotIn(opaque, result)
|
|
44
|
+
self.assertIn('[long value redacted]', result)
|
|
45
|
+
|
|
26
46
|
def test_truncated_first_line_and_small_proxy_credentials_cannot_escape(self):
|
|
27
47
|
body = b"x" * 17000 + b"TAIL_SECRET\n[!] Unable to satisfy dependency version 12.3.\n"
|
|
28
48
|
self.assertNotIn("TAIL_SECRET", diagnostic(io.BytesIO(body), {}))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.120
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.120
|