gowalk-cicd 1.0.89 → 1.0.90
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 -2
- package/README.md +1 -1
- package/action/.daemux-version +1 -1
- package/android-action/.daemux-version +1 -1
- package/android-action/scripts/flutter_download.py +2 -2
- package/android-action/scripts/flutter_manifest.py +1 -1
- package/android-action/scripts/flutter_manifest_fixture.py +3 -2
- package/android-action/scripts/test_flutter_archive_size.py +28 -0
- package/backend-action/.daemux-version +1 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -156,8 +156,8 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
156
156
|
consumer autoupdate changes the action directory. The installer delivers this development
|
|
157
157
|
tooling for native iOS repositories too; it does not require an Android app.
|
|
158
158
|
- Flutter manifest/archive GET recovery is scoped to the two pinned setup invocations through `BASH_ENV`.
|
|
159
|
-
It retains the account proxy and allows four attempts within 60 seconds for manifests or
|
|
160
|
-
for archives. Interrupted archives resume private
|
|
159
|
+
It retains the account proxy and allows four attempts within 60 seconds for manifests or 30 minutes
|
|
160
|
+
for archives, with an 8 GiB archive bound. Interrupted archives resume private bytes with HTTP Range; an origin ignoring
|
|
161
161
|
Range permits a bounded full restart. Only complete JSON or an archive matching the selected official
|
|
162
162
|
manifest's SHA-256 enters action outputs. Authentication/certificate refusals remain terminal.
|
|
163
163
|
`flutter_download_failed` emits fixed transport codes and retained-byte counts, never curl stderr.
|
package/README.md
CHANGED
|
@@ -1071,7 +1071,7 @@ reservation is never reused; delete such a reservation only after reading it bac
|
|
|
1071
1071
|
All requests and parts still use the Apple proxy.
|
|
1072
1072
|
|
|
1073
1073
|
Flutter SDK setup retries interrupted manifest and archive GETs on the assigned proxy, with four attempts
|
|
1074
|
-
within 60 seconds for manifests or
|
|
1074
|
+
within 60 seconds for manifests or 30 minutes for archives, with an 8 GiB archive bound. Retries resume private bytes
|
|
1075
1075
|
with HTTP Range; if the origin ignores Range, a bounded full restart is permitted. The completed archive
|
|
1076
1076
|
must match the selected official manifest's SHA-256 before extraction. Authentication and certificate
|
|
1077
1077
|
refusals remain terminal. Exhausted transfers emit `flutter_download_failed` with fixed status codes and
|
package/action/.daemux-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.90
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.90
|
|
@@ -8,7 +8,7 @@ import shutil
|
|
|
8
8
|
import subprocess
|
|
9
9
|
import sys
|
|
10
10
|
|
|
11
|
-
MAX_ARCHIVE_BYTES =
|
|
11
|
+
MAX_ARCHIVE_BYTES = 8 * 1024 * 1024 * 1024
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def archive_digest() -> str:
|
|
@@ -21,7 +21,7 @@ def archive_digest() -> str:
|
|
|
21
21
|
def transfer(url: str, destination: Path, kind: str, remaining: float, env: dict) -> tuple[int, int, int]:
|
|
22
22
|
resume = kind == "archive" and destination.stat().st_size > 0
|
|
23
23
|
command = ["curl", "--disable", "--silent", "--show-error", "--fail", "--retry", "0",
|
|
24
|
-
"--connect-timeout", "15", "--max-time", str(min(20 if kind == "manifest" else
|
|
24
|
+
"--connect-timeout", "15", "--max-time", str(min(20 if kind == "manifest" else 600, remaining)),
|
|
25
25
|
"--max-filesize", str(16777216 if kind == "manifest" else MAX_ARCHIVE_BYTES),
|
|
26
26
|
"--output", str(destination), "--write-out", "%{http_code} %{http_connect}"]
|
|
27
27
|
if resume:
|
|
@@ -22,7 +22,7 @@ def download(arguments: list[str], directory: Path) -> int:
|
|
|
22
22
|
if kind == "archive":
|
|
23
23
|
flutter_download.archive_digest()
|
|
24
24
|
child_env = {**os.environ, "NO_PROXY": "", "no_proxy": ""}
|
|
25
|
-
deadline, code, http, proxy_http = time.monotonic() + (60 if kind == "manifest" else
|
|
25
|
+
deadline, code, http, proxy_http = time.monotonic() + (60 if kind == "manifest" else 1800), 1, 0, 0
|
|
26
26
|
destination = directory / "download"
|
|
27
27
|
destination.touch(mode=0o600, exist_ok=False)
|
|
28
28
|
destination.chmod(0o600)
|
|
@@ -42,11 +42,12 @@ def response(server, mode, headers, path):
|
|
|
42
42
|
start = int(requested[6:-1])
|
|
43
43
|
extra = f"Content-Range: bytes {start}-{len(complete) - 1}/{len(complete)}\r\n".encode()
|
|
44
44
|
complete, status = complete[start:], b"206 Partial Content"
|
|
45
|
-
body = complete[:31] if mode in {"partial", "range_partial"} else complete
|
|
45
|
+
body = complete[:31] if mode in {"partial", "range_partial", "large_partial", "too_large"} else complete
|
|
46
46
|
if mode == "range_corrupt":
|
|
47
47
|
body = bytes([body[0] ^ 1]) + body[1:]
|
|
48
|
+
size = {"large_partial": 2 * 1024 ** 3 + 1, "too_large": 9 * 1024 ** 3}.get(mode, len(complete))
|
|
48
49
|
return (b"HTTP/1.1 " + status + b"\r\n" + extra + b"Content-Length: "
|
|
49
|
-
+ str(
|
|
50
|
+
+ str(size).encode() + b"\r\nConnection: close\r\n\r\n" + body)
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
class Proxy(socketserver.StreamRequestHandler):
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Current multi-gigabyte SDK response sizes remain recoverable through the real curl transport."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import tempfile
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
import test_flutter_archive as archive_fixture
|
|
7
|
+
from flutter_manifest_fixture import tls_proxy
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ArchiveSizeTests(unittest.TestCase):
|
|
11
|
+
def test_advertised_sdk_size_above_two_gib_does_not_prevent_recovery(self):
|
|
12
|
+
with tempfile.TemporaryDirectory() as directory:
|
|
13
|
+
root = Path(directory)
|
|
14
|
+
with tls_proxy(root, ["large_partial", "range"], archive_fixture.ARCHIVE) as (server, cert):
|
|
15
|
+
result = archive_fixture.ArchiveRecoveryTests().invoke(root, server, cert)
|
|
16
|
+
self.assertEqual((result.returncode, result.stdout), (0, archive_fixture.ARCHIVE))
|
|
17
|
+
self.assertEqual(server.ranges, ["", "bytes=31-"])
|
|
18
|
+
|
|
19
|
+
def test_archive_size_limit_still_refuses_oversized_transfers(self):
|
|
20
|
+
with tempfile.TemporaryDirectory() as directory:
|
|
21
|
+
root = Path(directory)
|
|
22
|
+
with tls_proxy(root, ["too_large"], archive_fixture.ARCHIVE) as (server, cert):
|
|
23
|
+
result = archive_fixture.ArchiveRecoveryTests().invoke(root, server, cert)
|
|
24
|
+
self.assertEqual((result.returncode, result.stdout, server.connects), (63, b"", 1))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
unittest.main()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.90
|