perf(build): stream normalization + ZIP emission for uploads - #1498

Merged
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization
Aug 29, 2026
Merged

perf(build): stream normalization + ZIP emission for uploads#1498
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization

Conversation

@jared-outpost

Copy link
Copy Markdown
Contributor

Converts the shared sentry build upload normalization path to stream builds through temp files instead of buffering the artifact plus the deterministic wrapper in memory at once (previously bounded only by Node's ~2 GiB Buffer cap). A new STORE-only streaming ZIP writer produces byte-for-byte identical wrapper bytes to the old fflate.zipSync encoding, so chunk dedup across re-uploads is unaffected.

Testing

  • vitest run test/lib/build test/commands/build test/lib/api — 601 passing (adds byte-parity tests for the new writer against zipSync, plus a large-payload streaming case and backward-compat checks)
  • tsc --noEmit clean; biome check ./ clean

Closes#1497

Convert the shared `sentry build upload` normalization path to stream builds
through temp files instead of buffering the artifact plus the wrapper in memory
at once (previously bounded only by Node's ~2 GiB Buffer cap).
- Add a deterministic STORE-only streaming ZIP writer that is byte-for-byte
identical to the previous fflate `zipSync` encoding (local headers, central
directory, EOCD, host-OS + external attrs), so wrapper determinism — and thus
chunk dedup across re-uploads — is unchanged.
- Rewrite `normalizeBuildFile`, `normalizeBuildDirectory`, and `normalizeIpa` to
write the wrapper to a destination path, streaming file bytes one entry at a
time. The IPA path stream-unzips to staged temp files rather than decompressing
the whole archive in memory.
- Add `detectBuildFormatFromFile` (streaming, local-headers-only) so the command
no longer reads the entire build into memory just to classify it.
- Switch `uploadBuild` to the file-based chunk path (`hashChunks` /
`uploadMissingChunks`), matching the sourcemaps upload.
Fixes#1497
@vercel

vercelBot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
cliReadyReadyPreviewAug 27, 2026 2:21pm

Request Review

@jared-outpost
jared-outpostBot marked this pull request as ready for review August 27, 2026 14:13
@github-actionsgithub-actionsBot added the risk: high PR risk score: high label Aug 27, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74caa76. Configure here.

Comment threadpackages/cli/src/lib/build/index.ts
…ing unzip
stageIpaPayload and detectBuildFormatFromFile now register both UnzipInflate and UnzipPassThrough so the streaming Unzip can handle STORE (method 0) entries, matching the previous unzipSync behavior and the existing snapshot extractor in the repo. Fixes the reported IPA normalization failure for real IPAs containing uncompressed files or directory markers.
Fixes the Cursor Bugbot high-severity finding.
Comment threadpackages/cli/src/lib/build/index.ts
@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, don't we already have yauzl or some other library that can do our newly-written zip-writer module? I'd rather not reinvent the wheel and then support our custom implementation.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

yauzl is a reader (we already pull it transitively). fflate's streaming Zip emits data descriptors so its output diverges from zipSync; the new writer replicates the exact STORE + 1980 mtime + sorted + unix-attr layout that dedup depends on. happy to drop it if a maintained writer can be shown to match byte-for-byte.

@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, do a deep research to see if you can find an existing and light library for your custom code and see if we can replace it.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

researched: yazl, archiver, compressing, jszip, zip-stream, node-stream-zip. none produce byte-identical output to fflate zipSync (STORE + 1980 mtime + sorted + unix attrs + no data descriptors). yazl is closest for writing but defaults to different mtime/flags and would require the same header/central-dir replication we have now. keeping the minimal custom writer avoids a heavier dep and guarantees the dedup contract. if a lib surfaces that matches exactly we can swap later.

@BYK
BYK merged commit b3a5e22 into mainAug 29, 2026
34 checks passed
@BYK
BYK deleted the issue-1497-stream-normalization branch August 29, 2026 12:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: highPR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build upload: stream normalization + ZIP emission instead of buffering artifacts in memory

1 participant

@BYK
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

perf(build): stream normalization + ZIP emission for uploads - #1498

Merged
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization
Aug 29, 2026
Merged

perf(build): stream normalization + ZIP emission for uploads#1498
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization

Conversation

@jared-outpost

Copy link
Copy Markdown
Contributor

Converts the shared sentry build upload normalization path to stream builds through temp files instead of buffering the artifact plus the deterministic wrapper in memory at once (previously bounded only by Node's ~2 GiB Buffer cap). A new STORE-only streaming ZIP writer produces byte-for-byte identical wrapper bytes to the old fflate.zipSync encoding, so chunk dedup across re-uploads is unaffected.

Testing

  • vitest run test/lib/build test/commands/build test/lib/api — 601 passing (adds byte-parity tests for the new writer against zipSync, plus a large-payload streaming case and backward-compat checks)
  • tsc --noEmit clean; biome check ./ clean

Closes#1497

Convert the shared `sentry build upload` normalization path to stream builds
through temp files instead of buffering the artifact plus the wrapper in memory
at once (previously bounded only by Node's ~2 GiB Buffer cap).
- Add a deterministic STORE-only streaming ZIP writer that is byte-for-byte
identical to the previous fflate `zipSync` encoding (local headers, central
directory, EOCD, host-OS + external attrs), so wrapper determinism — and thus
chunk dedup across re-uploads — is unchanged.
- Rewrite `normalizeBuildFile`, `normalizeBuildDirectory`, and `normalizeIpa` to
write the wrapper to a destination path, streaming file bytes one entry at a
time. The IPA path stream-unzips to staged temp files rather than decompressing
the whole archive in memory.
- Add `detectBuildFormatFromFile` (streaming, local-headers-only) so the command
no longer reads the entire build into memory just to classify it.
- Switch `uploadBuild` to the file-based chunk path (`hashChunks` /
`uploadMissingChunks`), matching the sourcemaps upload.
Fixes#1497
@vercel

vercelBot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
cliReadyReadyPreviewAug 27, 2026 2:21pm

Request Review

@jared-outpost
jared-outpostBot marked this pull request as ready for review August 27, 2026 14:13
@github-actionsgithub-actionsBot added the risk: high PR risk score: high label Aug 27, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74caa76. Configure here.

Comment threadpackages/cli/src/lib/build/index.ts
…ing unzip
stageIpaPayload and detectBuildFormatFromFile now register both UnzipInflate and UnzipPassThrough so the streaming Unzip can handle STORE (method 0) entries, matching the previous unzipSync behavior and the existing snapshot extractor in the repo. Fixes the reported IPA normalization failure for real IPAs containing uncompressed files or directory markers.
Fixes the Cursor Bugbot high-severity finding.
Comment threadpackages/cli/src/lib/build/index.ts
@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, don't we already have yauzl or some other library that can do our newly-written zip-writer module? I'd rather not reinvent the wheel and then support our custom implementation.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

yauzl is a reader (we already pull it transitively). fflate's streaming Zip emits data descriptors so its output diverges from zipSync; the new writer replicates the exact STORE + 1980 mtime + sorted + unix-attr layout that dedup depends on. happy to drop it if a maintained writer can be shown to match byte-for-byte.

@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, do a deep research to see if you can find an existing and light library for your custom code and see if we can replace it.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

researched: yazl, archiver, compressing, jszip, zip-stream, node-stream-zip. none produce byte-identical output to fflate zipSync (STORE + 1980 mtime + sorted + unix attrs + no data descriptors). yazl is closest for writing but defaults to different mtime/flags and would require the same header/central-dir replication we have now. keeping the minimal custom writer avoids a heavier dep and guarantees the dedup contract. if a lib surfaces that matches exactly we can swap later.

@BYK
BYK merged commit b3a5e22 into mainAug 29, 2026
34 checks passed
@BYK
BYK deleted the issue-1497-stream-normalization branch August 29, 2026 12:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: highPR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build upload: stream normalization + ZIP emission instead of buffering artifacts in memory

1 participant

@BYK
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(build): stream normalization + ZIP emission for uploads - #1498

Merged
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization
Aug 29, 2026
Merged

perf(build): stream normalization + ZIP emission for uploads#1498
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization

Conversation

@jared-outpost

Copy link
Copy Markdown
Contributor

Converts the shared sentry build upload normalization path to stream builds through temp files instead of buffering the artifact plus the deterministic wrapper in memory at once (previously bounded only by Node's ~2 GiB Buffer cap). A new STORE-only streaming ZIP writer produces byte-for-byte identical wrapper bytes to the old fflate.zipSync encoding, so chunk dedup across re-uploads is unaffected.

Testing

  • vitest run test/lib/build test/commands/build test/lib/api — 601 passing (adds byte-parity tests for the new writer against zipSync, plus a large-payload streaming case and backward-compat checks)
  • tsc --noEmit clean; biome check ./ clean

Closes#1497

Convert the shared `sentry build upload` normalization path to stream builds
through temp files instead of buffering the artifact plus the wrapper in memory
at once (previously bounded only by Node's ~2 GiB Buffer cap).
- Add a deterministic STORE-only streaming ZIP writer that is byte-for-byte
identical to the previous fflate `zipSync` encoding (local headers, central
directory, EOCD, host-OS + external attrs), so wrapper determinism — and thus
chunk dedup across re-uploads — is unchanged.
- Rewrite `normalizeBuildFile`, `normalizeBuildDirectory`, and `normalizeIpa` to
write the wrapper to a destination path, streaming file bytes one entry at a
time. The IPA path stream-unzips to staged temp files rather than decompressing
the whole archive in memory.
- Add `detectBuildFormatFromFile` (streaming, local-headers-only) so the command
no longer reads the entire build into memory just to classify it.
- Switch `uploadBuild` to the file-based chunk path (`hashChunks` /
`uploadMissingChunks`), matching the sourcemaps upload.
Fixes#1497
@vercel

vercelBot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
cliReadyReadyPreviewAug 27, 2026 2:21pm

Request Review

@jared-outpost
jared-outpostBot marked this pull request as ready for review August 27, 2026 14:13
@github-actionsgithub-actionsBot added the risk: high PR risk score: high label Aug 27, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74caa76. Configure here.

Comment threadpackages/cli/src/lib/build/index.ts
…ing unzip
stageIpaPayload and detectBuildFormatFromFile now register both UnzipInflate and UnzipPassThrough so the streaming Unzip can handle STORE (method 0) entries, matching the previous unzipSync behavior and the existing snapshot extractor in the repo. Fixes the reported IPA normalization failure for real IPAs containing uncompressed files or directory markers.
Fixes the Cursor Bugbot high-severity finding.
Comment threadpackages/cli/src/lib/build/index.ts
@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, don't we already have yauzl or some other library that can do our newly-written zip-writer module? I'd rather not reinvent the wheel and then support our custom implementation.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

yauzl is a reader (we already pull it transitively). fflate's streaming Zip emits data descriptors so its output diverges from zipSync; the new writer replicates the exact STORE + 1980 mtime + sorted + unix-attr layout that dedup depends on. happy to drop it if a maintained writer can be shown to match byte-for-byte.

@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, do a deep research to see if you can find an existing and light library for your custom code and see if we can replace it.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

researched: yazl, archiver, compressing, jszip, zip-stream, node-stream-zip. none produce byte-identical output to fflate zipSync (STORE + 1980 mtime + sorted + unix attrs + no data descriptors). yazl is closest for writing but defaults to different mtime/flags and would require the same header/central-dir replication we have now. keeping the minimal custom writer avoids a heavier dep and guarantees the dedup contract. if a lib surfaces that matches exactly we can swap later.

@BYK
BYK merged commit b3a5e22 into mainAug 29, 2026
34 checks passed
@BYK
BYK deleted the issue-1497-stream-normalization branch August 29, 2026 12:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: highPR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build upload: stream normalization + ZIP emission instead of buffering artifacts in memory

1 participant

@BYK
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(build): stream normalization + ZIP emission for uploads - #1498

Merged
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization
Aug 29, 2026
Merged

perf(build): stream normalization + ZIP emission for uploads#1498
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization

Conversation

@jared-outpost

Copy link
Copy Markdown
Contributor

Converts the shared sentry build upload normalization path to stream builds through temp files instead of buffering the artifact plus the deterministic wrapper in memory at once (previously bounded only by Node's ~2 GiB Buffer cap). A new STORE-only streaming ZIP writer produces byte-for-byte identical wrapper bytes to the old fflate.zipSync encoding, so chunk dedup across re-uploads is unaffected.

Testing

  • vitest run test/lib/build test/commands/build test/lib/api — 601 passing (adds byte-parity tests for the new writer against zipSync, plus a large-payload streaming case and backward-compat checks)
  • tsc --noEmit clean; biome check ./ clean

Closes#1497

Convert the shared `sentry build upload` normalization path to stream builds
through temp files instead of buffering the artifact plus the wrapper in memory
at once (previously bounded only by Node's ~2 GiB Buffer cap).
- Add a deterministic STORE-only streaming ZIP writer that is byte-for-byte
identical to the previous fflate `zipSync` encoding (local headers, central
directory, EOCD, host-OS + external attrs), so wrapper determinism — and thus
chunk dedup across re-uploads — is unchanged.
- Rewrite `normalizeBuildFile`, `normalizeBuildDirectory`, and `normalizeIpa` to
write the wrapper to a destination path, streaming file bytes one entry at a
time. The IPA path stream-unzips to staged temp files rather than decompressing
the whole archive in memory.
- Add `detectBuildFormatFromFile` (streaming, local-headers-only) so the command
no longer reads the entire build into memory just to classify it.
- Switch `uploadBuild` to the file-based chunk path (`hashChunks` /
`uploadMissingChunks`), matching the sourcemaps upload.
Fixes#1497
@vercel

vercelBot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
cliReadyReadyPreviewAug 27, 2026 2:21pm

Request Review

@jared-outpost
jared-outpostBot marked this pull request as ready for review August 27, 2026 14:13
@github-actionsgithub-actionsBot added the risk: high PR risk score: high label Aug 27, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74caa76. Configure here.

Comment threadpackages/cli/src/lib/build/index.ts
…ing unzip
stageIpaPayload and detectBuildFormatFromFile now register both UnzipInflate and UnzipPassThrough so the streaming Unzip can handle STORE (method 0) entries, matching the previous unzipSync behavior and the existing snapshot extractor in the repo. Fixes the reported IPA normalization failure for real IPAs containing uncompressed files or directory markers.
Fixes the Cursor Bugbot high-severity finding.
Comment threadpackages/cli/src/lib/build/index.ts
@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, don't we already have yauzl or some other library that can do our newly-written zip-writer module? I'd rather not reinvent the wheel and then support our custom implementation.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

yauzl is a reader (we already pull it transitively). fflate's streaming Zip emits data descriptors so its output diverges from zipSync; the new writer replicates the exact STORE + 1980 mtime + sorted + unix-attr layout that dedup depends on. happy to drop it if a maintained writer can be shown to match byte-for-byte.

@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, do a deep research to see if you can find an existing and light library for your custom code and see if we can replace it.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

researched: yazl, archiver, compressing, jszip, zip-stream, node-stream-zip. none produce byte-identical output to fflate zipSync (STORE + 1980 mtime + sorted + unix attrs + no data descriptors). yazl is closest for writing but defaults to different mtime/flags and would require the same header/central-dir replication we have now. keeping the minimal custom writer avoids a heavier dep and guarantees the dedup contract. if a lib surfaces that matches exactly we can swap later.

@BYK
BYK merged commit b3a5e22 into mainAug 29, 2026
34 checks passed
@BYK
BYK deleted the issue-1497-stream-normalization branch August 29, 2026 12:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: highPR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build upload: stream normalization + ZIP emission instead of buffering artifacts in memory

1 participant

@BYK
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

perf(build): stream normalization + ZIP emission for uploads - #1498

Merged
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization
Aug 29, 2026
Merged

perf(build): stream normalization + ZIP emission for uploads#1498
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization

Conversation

@jared-outpost

Copy link
Copy Markdown
Contributor

Converts the shared sentry build upload normalization path to stream builds through temp files instead of buffering the artifact plus the deterministic wrapper in memory at once (previously bounded only by Node's ~2 GiB Buffer cap). A new STORE-only streaming ZIP writer produces byte-for-byte identical wrapper bytes to the old fflate.zipSync encoding, so chunk dedup across re-uploads is unaffected.

Testing

  • vitest run test/lib/build test/commands/build test/lib/api — 601 passing (adds byte-parity tests for the new writer against zipSync, plus a large-payload streaming case and backward-compat checks)
  • tsc --noEmit clean; biome check ./ clean

Closes#1497

Convert the shared `sentry build upload` normalization path to stream builds
through temp files instead of buffering the artifact plus the wrapper in memory
at once (previously bounded only by Node's ~2 GiB Buffer cap).
- Add a deterministic STORE-only streaming ZIP writer that is byte-for-byte
identical to the previous fflate `zipSync` encoding (local headers, central
directory, EOCD, host-OS + external attrs), so wrapper determinism — and thus
chunk dedup across re-uploads — is unchanged.
- Rewrite `normalizeBuildFile`, `normalizeBuildDirectory`, and `normalizeIpa` to
write the wrapper to a destination path, streaming file bytes one entry at a
time. The IPA path stream-unzips to staged temp files rather than decompressing
the whole archive in memory.
- Add `detectBuildFormatFromFile` (streaming, local-headers-only) so the command
no longer reads the entire build into memory just to classify it.
- Switch `uploadBuild` to the file-based chunk path (`hashChunks` /
`uploadMissingChunks`), matching the sourcemaps upload.
Fixes#1497
@vercel

vercelBot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
cliReadyReadyPreviewAug 27, 2026 2:21pm

Request Review

@jared-outpost
jared-outpostBot marked this pull request as ready for review August 27, 2026 14:13
@github-actionsgithub-actionsBot added the risk: high PR risk score: high label Aug 27, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74caa76. Configure here.

Comment threadpackages/cli/src/lib/build/index.ts
…ing unzip
stageIpaPayload and detectBuildFormatFromFile now register both UnzipInflate and UnzipPassThrough so the streaming Unzip can handle STORE (method 0) entries, matching the previous unzipSync behavior and the existing snapshot extractor in the repo. Fixes the reported IPA normalization failure for real IPAs containing uncompressed files or directory markers.
Fixes the Cursor Bugbot high-severity finding.
Comment threadpackages/cli/src/lib/build/index.ts
@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, don't we already have yauzl or some other library that can do our newly-written zip-writer module? I'd rather not reinvent the wheel and then support our custom implementation.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

yauzl is a reader (we already pull it transitively). fflate's streaming Zip emits data descriptors so its output diverges from zipSync; the new writer replicates the exact STORE + 1980 mtime + sorted + unix-attr layout that dedup depends on. happy to drop it if a maintained writer can be shown to match byte-for-byte.

@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, do a deep research to see if you can find an existing and light library for your custom code and see if we can replace it.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

researched: yazl, archiver, compressing, jszip, zip-stream, node-stream-zip. none produce byte-identical output to fflate zipSync (STORE + 1980 mtime + sorted + unix attrs + no data descriptors). yazl is closest for writing but defaults to different mtime/flags and would require the same header/central-dir replication we have now. keeping the minimal custom writer avoids a heavier dep and guarantees the dedup contract. if a lib surfaces that matches exactly we can swap later.

@BYK
BYK merged commit b3a5e22 into mainAug 29, 2026
34 checks passed
@BYK
BYK deleted the issue-1497-stream-normalization branch August 29, 2026 12:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: highPR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build upload: stream normalization + ZIP emission instead of buffering artifacts in memory

1 participant

@BYK
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(build): stream normalization + ZIP emission for uploads - #1498

Merged
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization
Aug 29, 2026
Merged

perf(build): stream normalization + ZIP emission for uploads#1498
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization

Conversation

@jared-outpost

Copy link
Copy Markdown
Contributor

Converts the shared sentry build upload normalization path to stream builds through temp files instead of buffering the artifact plus the deterministic wrapper in memory at once (previously bounded only by Node's ~2 GiB Buffer cap). A new STORE-only streaming ZIP writer produces byte-for-byte identical wrapper bytes to the old fflate.zipSync encoding, so chunk dedup across re-uploads is unaffected.

Testing

  • vitest run test/lib/build test/commands/build test/lib/api — 601 passing (adds byte-parity tests for the new writer against zipSync, plus a large-payload streaming case and backward-compat checks)
  • tsc --noEmit clean; biome check ./ clean

Closes#1497

Convert the shared `sentry build upload` normalization path to stream builds
through temp files instead of buffering the artifact plus the wrapper in memory
at once (previously bounded only by Node's ~2 GiB Buffer cap).
- Add a deterministic STORE-only streaming ZIP writer that is byte-for-byte
identical to the previous fflate `zipSync` encoding (local headers, central
directory, EOCD, host-OS + external attrs), so wrapper determinism — and thus
chunk dedup across re-uploads — is unchanged.
- Rewrite `normalizeBuildFile`, `normalizeBuildDirectory`, and `normalizeIpa` to
write the wrapper to a destination path, streaming file bytes one entry at a
time. The IPA path stream-unzips to staged temp files rather than decompressing
the whole archive in memory.
- Add `detectBuildFormatFromFile` (streaming, local-headers-only) so the command
no longer reads the entire build into memory just to classify it.
- Switch `uploadBuild` to the file-based chunk path (`hashChunks` /
`uploadMissingChunks`), matching the sourcemaps upload.
Fixes#1497
@vercel

vercelBot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
cliReadyReadyPreviewAug 27, 2026 2:21pm

Request Review

@jared-outpost
jared-outpostBot marked this pull request as ready for review August 27, 2026 14:13
@github-actionsgithub-actionsBot added the risk: high PR risk score: high label Aug 27, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74caa76. Configure here.

Comment threadpackages/cli/src/lib/build/index.ts
…ing unzip
stageIpaPayload and detectBuildFormatFromFile now register both UnzipInflate and UnzipPassThrough so the streaming Unzip can handle STORE (method 0) entries, matching the previous unzipSync behavior and the existing snapshot extractor in the repo. Fixes the reported IPA normalization failure for real IPAs containing uncompressed files or directory markers.
Fixes the Cursor Bugbot high-severity finding.
Comment threadpackages/cli/src/lib/build/index.ts
@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, don't we already have yauzl or some other library that can do our newly-written zip-writer module? I'd rather not reinvent the wheel and then support our custom implementation.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

yauzl is a reader (we already pull it transitively). fflate's streaming Zip emits data descriptors so its output diverges from zipSync; the new writer replicates the exact STORE + 1980 mtime + sorted + unix-attr layout that dedup depends on. happy to drop it if a maintained writer can be shown to match byte-for-byte.

@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, do a deep research to see if you can find an existing and light library for your custom code and see if we can replace it.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

researched: yazl, archiver, compressing, jszip, zip-stream, node-stream-zip. none produce byte-identical output to fflate zipSync (STORE + 1980 mtime + sorted + unix attrs + no data descriptors). yazl is closest for writing but defaults to different mtime/flags and would require the same header/central-dir replication we have now. keeping the minimal custom writer avoids a heavier dep and guarantees the dedup contract. if a lib surfaces that matches exactly we can swap later.

@BYK
BYK merged commit b3a5e22 into mainAug 29, 2026
34 checks passed
@BYK
BYK deleted the issue-1497-stream-normalization branch August 29, 2026 12:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: highPR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build upload: stream normalization + ZIP emission instead of buffering artifacts in memory

1 participant

@BYK
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(build): stream normalization + ZIP emission for uploads - #1498

Merged
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization
Aug 29, 2026
Merged

perf(build): stream normalization + ZIP emission for uploads#1498
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization

Conversation

@jared-outpost

Copy link
Copy Markdown
Contributor

Converts the shared sentry build upload normalization path to stream builds through temp files instead of buffering the artifact plus the deterministic wrapper in memory at once (previously bounded only by Node's ~2 GiB Buffer cap). A new STORE-only streaming ZIP writer produces byte-for-byte identical wrapper bytes to the old fflate.zipSync encoding, so chunk dedup across re-uploads is unaffected.

Testing

  • vitest run test/lib/build test/commands/build test/lib/api — 601 passing (adds byte-parity tests for the new writer against zipSync, plus a large-payload streaming case and backward-compat checks)
  • tsc --noEmit clean; biome check ./ clean

Closes#1497

Convert the shared `sentry build upload` normalization path to stream builds
through temp files instead of buffering the artifact plus the wrapper in memory
at once (previously bounded only by Node's ~2 GiB Buffer cap).
- Add a deterministic STORE-only streaming ZIP writer that is byte-for-byte
identical to the previous fflate `zipSync` encoding (local headers, central
directory, EOCD, host-OS + external attrs), so wrapper determinism — and thus
chunk dedup across re-uploads — is unchanged.
- Rewrite `normalizeBuildFile`, `normalizeBuildDirectory`, and `normalizeIpa` to
write the wrapper to a destination path, streaming file bytes one entry at a
time. The IPA path stream-unzips to staged temp files rather than decompressing
the whole archive in memory.
- Add `detectBuildFormatFromFile` (streaming, local-headers-only) so the command
no longer reads the entire build into memory just to classify it.
- Switch `uploadBuild` to the file-based chunk path (`hashChunks` /
`uploadMissingChunks`), matching the sourcemaps upload.
Fixes#1497
@vercel

vercelBot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
cliReadyReadyPreviewAug 27, 2026 2:21pm

Request Review

@jared-outpost
jared-outpostBot marked this pull request as ready for review August 27, 2026 14:13
@github-actionsgithub-actionsBot added the risk: high PR risk score: high label Aug 27, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74caa76. Configure here.

Comment threadpackages/cli/src/lib/build/index.ts
…ing unzip
stageIpaPayload and detectBuildFormatFromFile now register both UnzipInflate and UnzipPassThrough so the streaming Unzip can handle STORE (method 0) entries, matching the previous unzipSync behavior and the existing snapshot extractor in the repo. Fixes the reported IPA normalization failure for real IPAs containing uncompressed files or directory markers.
Fixes the Cursor Bugbot high-severity finding.
Comment threadpackages/cli/src/lib/build/index.ts
@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, don't we already have yauzl or some other library that can do our newly-written zip-writer module? I'd rather not reinvent the wheel and then support our custom implementation.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

yauzl is a reader (we already pull it transitively). fflate's streaming Zip emits data descriptors so its output diverges from zipSync; the new writer replicates the exact STORE + 1980 mtime + sorted + unix-attr layout that dedup depends on. happy to drop it if a maintained writer can be shown to match byte-for-byte.

@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, do a deep research to see if you can find an existing and light library for your custom code and see if we can replace it.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

researched: yazl, archiver, compressing, jszip, zip-stream, node-stream-zip. none produce byte-identical output to fflate zipSync (STORE + 1980 mtime + sorted + unix attrs + no data descriptors). yazl is closest for writing but defaults to different mtime/flags and would require the same header/central-dir replication we have now. keeping the minimal custom writer avoids a heavier dep and guarantees the dedup contract. if a lib surfaces that matches exactly we can swap later.

@BYK
BYK merged commit b3a5e22 into mainAug 29, 2026
34 checks passed
@BYK
BYK deleted the issue-1497-stream-normalization branch August 29, 2026 12:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: highPR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build upload: stream normalization + ZIP emission instead of buffering artifacts in memory

1 participant

@BYK
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

perf(build): stream normalization + ZIP emission for uploads - #1498

Merged
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization
Aug 29, 2026
Merged

perf(build): stream normalization + ZIP emission for uploads#1498
BYK merged 2 commits into
mainfrom
issue-1497-stream-normalization

Conversation

@jared-outpost

Copy link
Copy Markdown
Contributor

Converts the shared sentry build upload normalization path to stream builds through temp files instead of buffering the artifact plus the deterministic wrapper in memory at once (previously bounded only by Node's ~2 GiB Buffer cap). A new STORE-only streaming ZIP writer produces byte-for-byte identical wrapper bytes to the old fflate.zipSync encoding, so chunk dedup across re-uploads is unaffected.

Testing

  • vitest run test/lib/build test/commands/build test/lib/api — 601 passing (adds byte-parity tests for the new writer against zipSync, plus a large-payload streaming case and backward-compat checks)
  • tsc --noEmit clean; biome check ./ clean

Closes#1497

Convert the shared `sentry build upload` normalization path to stream builds
through temp files instead of buffering the artifact plus the wrapper in memory
at once (previously bounded only by Node's ~2 GiB Buffer cap).
- Add a deterministic STORE-only streaming ZIP writer that is byte-for-byte
identical to the previous fflate `zipSync` encoding (local headers, central
directory, EOCD, host-OS + external attrs), so wrapper determinism — and thus
chunk dedup across re-uploads — is unchanged.
- Rewrite `normalizeBuildFile`, `normalizeBuildDirectory`, and `normalizeIpa` to
write the wrapper to a destination path, streaming file bytes one entry at a
time. The IPA path stream-unzips to staged temp files rather than decompressing
the whole archive in memory.
- Add `detectBuildFormatFromFile` (streaming, local-headers-only) so the command
no longer reads the entire build into memory just to classify it.
- Switch `uploadBuild` to the file-based chunk path (`hashChunks` /
`uploadMissingChunks`), matching the sourcemaps upload.
Fixes#1497
@vercel

vercelBot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
cliReadyReadyPreviewAug 27, 2026 2:21pm

Request Review

@jared-outpost
jared-outpostBot marked this pull request as ready for review August 27, 2026 14:13
@github-actionsgithub-actionsBot added the risk: high PR risk score: high label Aug 27, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74caa76. Configure here.

Comment threadpackages/cli/src/lib/build/index.ts
…ing unzip
stageIpaPayload and detectBuildFormatFromFile now register both UnzipInflate and UnzipPassThrough so the streaming Unzip can handle STORE (method 0) entries, matching the previous unzipSync behavior and the existing snapshot extractor in the repo. Fixes the reported IPA normalization failure for real IPAs containing uncompressed files or directory markers.
Fixes the Cursor Bugbot high-severity finding.
Comment threadpackages/cli/src/lib/build/index.ts
@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, don't we already have yauzl or some other library that can do our newly-written zip-writer module? I'd rather not reinvent the wheel and then support our custom implementation.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

yauzl is a reader (we already pull it transitively). fflate's streaming Zip emits data descriptors so its output diverges from zipSync; the new writer replicates the exact STORE + 1980 mtime + sorted + unix-attr layout that dedup depends on. happy to drop it if a maintained writer can be shown to match byte-for-byte.

@BYK

BYK commented Aug 29, 2026

Copy link
Copy Markdown
Member

Jared, do a deep research to see if you can find an existing and light library for your custom code and see if we can replace it.

@jared-outpost

Copy link
Copy Markdown
ContributorAuthor

researched: yazl, archiver, compressing, jszip, zip-stream, node-stream-zip. none produce byte-identical output to fflate zipSync (STORE + 1980 mtime + sorted + unix attrs + no data descriptors). yazl is closest for writing but defaults to different mtime/flags and would require the same header/central-dir replication we have now. keeping the minimal custom writer avoids a heavier dep and guarantees the dedup contract. if a lib surfaces that matches exactly we can swap later.

@BYK
BYK merged commit b3a5e22 into mainAug 29, 2026
34 checks passed
@BYK
BYK deleted the issue-1497-stream-normalization branch August 29, 2026 12:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: highPR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build upload: stream normalization + ZIP emission instead of buffering artifacts in memory

1 participant

@BYK