fix(v4/webpack): Deduplicate webpack deploys (#875) - #888

Merged
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly
Feb 23, 2026
Merged

fix(v4/webpack): Deduplicate webpack deploys (#875)#888
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly

Conversation

@andreiborza

@andreiborzaandreiborza commented Feb 23, 2026

Copy link
Copy Markdown
Member

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)

  • Added a module-level guard (Set keyed by release name) so newDeploy only fires once per release per process
  • Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected

closes#873

Backport of #875 to v4.

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)
- Added a module-level guard (Set<string> keyed by release name) so newDeploy only fires once per release per process
- Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected
closes#873
@github-actions

github-actionsBot commented Feb 23, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

V4/Webpack


🤖 This preview updates automatically when you update the PR.

@cursorcursorBot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (options.release.deploy) {
if (options.release.deploy && !_deployedReleases.has(options.release.name)) {
await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);
_deployedReleases.add(options.release.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition in deploy deduplication guard

High Severity

The check-then-act pattern (has() check, then await, then add()) creates a race condition when multiple webpack compilers run concurrently. Both compilers can pass the has() check before either executes add(), causing duplicate deploy records—the exact bug this PR aims to fix. The deduplication requires the release name to be added to _deployedReleases before the await, not after.

Fix in CursorFix in Web

// Module-level guard to prevent duplicate deploy records when multiple bundler plugin
// instances run in the same process (e.g. Next.js creates separate webpack compilers
// for client, server, and edge). Keyed by release name.
const _deployedReleases = new Set<string>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unbounded Set growth in long-running processes

Low Severity

The _deployedReleases Set accumulates release names indefinitely without cleanup. Since release names typically use git SHAs or CI commit identifiers (changing with each build), the Set grows unbounded in long-running production build processes, causing a memory leak. While dev mode skips deploy creation, production CI/CD pipelines or continuous deployment systems could accumulate entries.

Fix in CursorFix in Web

);

await managerA.createRelease();
await managerB.createRelease();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests don't verify concurrent execution scenario

Medium Severity

The test "should not create duplicate deploy records across separate plugin instances" uses sequential await calls instead of Promise.all, so it doesn't actually test concurrent execution. The race condition in the deduplication logic would only manifest when both createRelease() calls run truly concurrently, which this test doesn't verify.

Fix in CursorFix in Web

@andreiborza
andreiborza merged commit 5d19ec0 into v4Feb 23, 2026
23 checks passed
@andreiborza
andreiborza deleted the ab/cherry-pick-charly branch February 23, 2026 12:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@andreiborza@chargome
, '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

fix(v4/webpack): Deduplicate webpack deploys (#875) - #888

Merged
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly
Feb 23, 2026
Merged

fix(v4/webpack): Deduplicate webpack deploys (#875)#888
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly

Conversation

@andreiborza

@andreiborzaandreiborza commented Feb 23, 2026

Copy link
Copy Markdown
Member

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)

  • Added a module-level guard (Set keyed by release name) so newDeploy only fires once per release per process
  • Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected

closes#873

Backport of #875 to v4.

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)
- Added a module-level guard (Set<string> keyed by release name) so newDeploy only fires once per release per process
- Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected
closes#873
@github-actions

github-actionsBot commented Feb 23, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

V4/Webpack


🤖 This preview updates automatically when you update the PR.

@cursorcursorBot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (options.release.deploy) {
if (options.release.deploy && !_deployedReleases.has(options.release.name)) {
await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);
_deployedReleases.add(options.release.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition in deploy deduplication guard

High Severity

The check-then-act pattern (has() check, then await, then add()) creates a race condition when multiple webpack compilers run concurrently. Both compilers can pass the has() check before either executes add(), causing duplicate deploy records—the exact bug this PR aims to fix. The deduplication requires the release name to be added to _deployedReleases before the await, not after.

Fix in CursorFix in Web

// Module-level guard to prevent duplicate deploy records when multiple bundler plugin
// instances run in the same process (e.g. Next.js creates separate webpack compilers
// for client, server, and edge). Keyed by release name.
const _deployedReleases = new Set<string>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unbounded Set growth in long-running processes

Low Severity

The _deployedReleases Set accumulates release names indefinitely without cleanup. Since release names typically use git SHAs or CI commit identifiers (changing with each build), the Set grows unbounded in long-running production build processes, causing a memory leak. While dev mode skips deploy creation, production CI/CD pipelines or continuous deployment systems could accumulate entries.

Fix in CursorFix in Web

);

await managerA.createRelease();
await managerB.createRelease();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests don't verify concurrent execution scenario

Medium Severity

The test "should not create duplicate deploy records across separate plugin instances" uses sequential await calls instead of Promise.all, so it doesn't actually test concurrent execution. The race condition in the deduplication logic would only manifest when both createRelease() calls run truly concurrently, which this test doesn't verify.

Fix in CursorFix in Web

@andreiborza
andreiborza merged commit 5d19ec0 into v4Feb 23, 2026
23 checks passed
@andreiborza
andreiborza deleted the ab/cherry-pick-charly branch February 23, 2026 12:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@andreiborza@chargome
, '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

fix(v4/webpack): Deduplicate webpack deploys (#875) - #888

Merged
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly
Feb 23, 2026
Merged

fix(v4/webpack): Deduplicate webpack deploys (#875)#888
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly

Conversation

@andreiborza

@andreiborzaandreiborza commented Feb 23, 2026

Copy link
Copy Markdown
Member

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)

  • Added a module-level guard (Set keyed by release name) so newDeploy only fires once per release per process
  • Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected

closes#873

Backport of #875 to v4.

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)
- Added a module-level guard (Set<string> keyed by release name) so newDeploy only fires once per release per process
- Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected
closes#873
@github-actions

github-actionsBot commented Feb 23, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

V4/Webpack


🤖 This preview updates automatically when you update the PR.

@cursorcursorBot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (options.release.deploy) {
if (options.release.deploy && !_deployedReleases.has(options.release.name)) {
await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);
_deployedReleases.add(options.release.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition in deploy deduplication guard

High Severity

The check-then-act pattern (has() check, then await, then add()) creates a race condition when multiple webpack compilers run concurrently. Both compilers can pass the has() check before either executes add(), causing duplicate deploy records—the exact bug this PR aims to fix. The deduplication requires the release name to be added to _deployedReleases before the await, not after.

Fix in CursorFix in Web

// Module-level guard to prevent duplicate deploy records when multiple bundler plugin
// instances run in the same process (e.g. Next.js creates separate webpack compilers
// for client, server, and edge). Keyed by release name.
const _deployedReleases = new Set<string>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unbounded Set growth in long-running processes

Low Severity

The _deployedReleases Set accumulates release names indefinitely without cleanup. Since release names typically use git SHAs or CI commit identifiers (changing with each build), the Set grows unbounded in long-running production build processes, causing a memory leak. While dev mode skips deploy creation, production CI/CD pipelines or continuous deployment systems could accumulate entries.

Fix in CursorFix in Web

);

await managerA.createRelease();
await managerB.createRelease();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests don't verify concurrent execution scenario

Medium Severity

The test "should not create duplicate deploy records across separate plugin instances" uses sequential await calls instead of Promise.all, so it doesn't actually test concurrent execution. The race condition in the deduplication logic would only manifest when both createRelease() calls run truly concurrently, which this test doesn't verify.

Fix in CursorFix in Web

@andreiborza
andreiborza merged commit 5d19ec0 into v4Feb 23, 2026
23 checks passed
@andreiborza
andreiborza deleted the ab/cherry-pick-charly branch February 23, 2026 12:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@andreiborza@chargome
, '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

fix(v4/webpack): Deduplicate webpack deploys (#875) - #888

Merged
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly
Feb 23, 2026
Merged

fix(v4/webpack): Deduplicate webpack deploys (#875)#888
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly

Conversation

@andreiborza

@andreiborzaandreiborza commented Feb 23, 2026

Copy link
Copy Markdown
Member

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)

  • Added a module-level guard (Set keyed by release name) so newDeploy only fires once per release per process
  • Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected

closes#873

Backport of #875 to v4.

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)
- Added a module-level guard (Set<string> keyed by release name) so newDeploy only fires once per release per process
- Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected
closes#873
@github-actions

github-actionsBot commented Feb 23, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

V4/Webpack


🤖 This preview updates automatically when you update the PR.

@cursorcursorBot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (options.release.deploy) {
if (options.release.deploy && !_deployedReleases.has(options.release.name)) {
await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);
_deployedReleases.add(options.release.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition in deploy deduplication guard

High Severity

The check-then-act pattern (has() check, then await, then add()) creates a race condition when multiple webpack compilers run concurrently. Both compilers can pass the has() check before either executes add(), causing duplicate deploy records—the exact bug this PR aims to fix. The deduplication requires the release name to be added to _deployedReleases before the await, not after.

Fix in CursorFix in Web

// Module-level guard to prevent duplicate deploy records when multiple bundler plugin
// instances run in the same process (e.g. Next.js creates separate webpack compilers
// for client, server, and edge). Keyed by release name.
const _deployedReleases = new Set<string>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unbounded Set growth in long-running processes

Low Severity

The _deployedReleases Set accumulates release names indefinitely without cleanup. Since release names typically use git SHAs or CI commit identifiers (changing with each build), the Set grows unbounded in long-running production build processes, causing a memory leak. While dev mode skips deploy creation, production CI/CD pipelines or continuous deployment systems could accumulate entries.

Fix in CursorFix in Web

);

await managerA.createRelease();
await managerB.createRelease();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests don't verify concurrent execution scenario

Medium Severity

The test "should not create duplicate deploy records across separate plugin instances" uses sequential await calls instead of Promise.all, so it doesn't actually test concurrent execution. The race condition in the deduplication logic would only manifest when both createRelease() calls run truly concurrently, which this test doesn't verify.

Fix in CursorFix in Web

@andreiborza
andreiborza merged commit 5d19ec0 into v4Feb 23, 2026
23 checks passed
@andreiborza
andreiborza deleted the ab/cherry-pick-charly branch February 23, 2026 12:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@andreiborza@chargome
, '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

fix(v4/webpack): Deduplicate webpack deploys (#875) - #888

Merged
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly
Feb 23, 2026
Merged

fix(v4/webpack): Deduplicate webpack deploys (#875)#888
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly

Conversation

@andreiborza

@andreiborzaandreiborza commented Feb 23, 2026

Copy link
Copy Markdown
Member

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)

  • Added a module-level guard (Set keyed by release name) so newDeploy only fires once per release per process
  • Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected

closes#873

Backport of #875 to v4.

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)
- Added a module-level guard (Set<string> keyed by release name) so newDeploy only fires once per release per process
- Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected
closes#873
@github-actions

github-actionsBot commented Feb 23, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

V4/Webpack


🤖 This preview updates automatically when you update the PR.

@cursorcursorBot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (options.release.deploy) {
if (options.release.deploy && !_deployedReleases.has(options.release.name)) {
await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);
_deployedReleases.add(options.release.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition in deploy deduplication guard

High Severity

The check-then-act pattern (has() check, then await, then add()) creates a race condition when multiple webpack compilers run concurrently. Both compilers can pass the has() check before either executes add(), causing duplicate deploy records—the exact bug this PR aims to fix. The deduplication requires the release name to be added to _deployedReleases before the await, not after.

Fix in CursorFix in Web

// Module-level guard to prevent duplicate deploy records when multiple bundler plugin
// instances run in the same process (e.g. Next.js creates separate webpack compilers
// for client, server, and edge). Keyed by release name.
const _deployedReleases = new Set<string>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unbounded Set growth in long-running processes

Low Severity

The _deployedReleases Set accumulates release names indefinitely without cleanup. Since release names typically use git SHAs or CI commit identifiers (changing with each build), the Set grows unbounded in long-running production build processes, causing a memory leak. While dev mode skips deploy creation, production CI/CD pipelines or continuous deployment systems could accumulate entries.

Fix in CursorFix in Web

);

await managerA.createRelease();
await managerB.createRelease();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests don't verify concurrent execution scenario

Medium Severity

The test "should not create duplicate deploy records across separate plugin instances" uses sequential await calls instead of Promise.all, so it doesn't actually test concurrent execution. The race condition in the deduplication logic would only manifest when both createRelease() calls run truly concurrently, which this test doesn't verify.

Fix in CursorFix in Web

@andreiborza
andreiborza merged commit 5d19ec0 into v4Feb 23, 2026
23 checks passed
@andreiborza
andreiborza deleted the ab/cherry-pick-charly branch February 23, 2026 12:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@andreiborza@chargome
, '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

fix(v4/webpack): Deduplicate webpack deploys (#875) - #888

Merged
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly
Feb 23, 2026
Merged

fix(v4/webpack): Deduplicate webpack deploys (#875)#888
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly

Conversation

@andreiborza

@andreiborzaandreiborza commented Feb 23, 2026

Copy link
Copy Markdown
Member

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)

  • Added a module-level guard (Set keyed by release name) so newDeploy only fires once per release per process
  • Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected

closes#873

Backport of #875 to v4.

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)
- Added a module-level guard (Set<string> keyed by release name) so newDeploy only fires once per release per process
- Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected
closes#873
@github-actions

github-actionsBot commented Feb 23, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

V4/Webpack


🤖 This preview updates automatically when you update the PR.

@cursorcursorBot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (options.release.deploy) {
if (options.release.deploy && !_deployedReleases.has(options.release.name)) {
await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);
_deployedReleases.add(options.release.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition in deploy deduplication guard

High Severity

The check-then-act pattern (has() check, then await, then add()) creates a race condition when multiple webpack compilers run concurrently. Both compilers can pass the has() check before either executes add(), causing duplicate deploy records—the exact bug this PR aims to fix. The deduplication requires the release name to be added to _deployedReleases before the await, not after.

Fix in CursorFix in Web

// Module-level guard to prevent duplicate deploy records when multiple bundler plugin
// instances run in the same process (e.g. Next.js creates separate webpack compilers
// for client, server, and edge). Keyed by release name.
const _deployedReleases = new Set<string>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unbounded Set growth in long-running processes

Low Severity

The _deployedReleases Set accumulates release names indefinitely without cleanup. Since release names typically use git SHAs or CI commit identifiers (changing with each build), the Set grows unbounded in long-running production build processes, causing a memory leak. While dev mode skips deploy creation, production CI/CD pipelines or continuous deployment systems could accumulate entries.

Fix in CursorFix in Web

);

await managerA.createRelease();
await managerB.createRelease();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests don't verify concurrent execution scenario

Medium Severity

The test "should not create duplicate deploy records across separate plugin instances" uses sequential await calls instead of Promise.all, so it doesn't actually test concurrent execution. The race condition in the deduplication logic would only manifest when both createRelease() calls run truly concurrently, which this test doesn't verify.

Fix in CursorFix in Web

@andreiborza
andreiborza merged commit 5d19ec0 into v4Feb 23, 2026
23 checks passed
@andreiborza
andreiborza deleted the ab/cherry-pick-charly branch February 23, 2026 12:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@andreiborza@chargome
, '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

fix(v4/webpack): Deduplicate webpack deploys (#875) - #888

Merged
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly
Feb 23, 2026
Merged

fix(v4/webpack): Deduplicate webpack deploys (#875)#888
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly

Conversation

@andreiborza

@andreiborzaandreiborza commented Feb 23, 2026

Copy link
Copy Markdown
Member

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)

  • Added a module-level guard (Set keyed by release name) so newDeploy only fires once per release per process
  • Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected

closes#873

Backport of #875 to v4.

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)
- Added a module-level guard (Set<string> keyed by release name) so newDeploy only fires once per release per process
- Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected
closes#873
@github-actions

github-actionsBot commented Feb 23, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

V4/Webpack


🤖 This preview updates automatically when you update the PR.

@cursorcursorBot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (options.release.deploy) {
if (options.release.deploy && !_deployedReleases.has(options.release.name)) {
await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);
_deployedReleases.add(options.release.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition in deploy deduplication guard

High Severity

The check-then-act pattern (has() check, then await, then add()) creates a race condition when multiple webpack compilers run concurrently. Both compilers can pass the has() check before either executes add(), causing duplicate deploy records—the exact bug this PR aims to fix. The deduplication requires the release name to be added to _deployedReleases before the await, not after.

Fix in CursorFix in Web

// Module-level guard to prevent duplicate deploy records when multiple bundler plugin
// instances run in the same process (e.g. Next.js creates separate webpack compilers
// for client, server, and edge). Keyed by release name.
const _deployedReleases = new Set<string>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unbounded Set growth in long-running processes

Low Severity

The _deployedReleases Set accumulates release names indefinitely without cleanup. Since release names typically use git SHAs or CI commit identifiers (changing with each build), the Set grows unbounded in long-running production build processes, causing a memory leak. While dev mode skips deploy creation, production CI/CD pipelines or continuous deployment systems could accumulate entries.

Fix in CursorFix in Web

);

await managerA.createRelease();
await managerB.createRelease();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests don't verify concurrent execution scenario

Medium Severity

The test "should not create duplicate deploy records across separate plugin instances" uses sequential await calls instead of Promise.all, so it doesn't actually test concurrent execution. The race condition in the deduplication logic would only manifest when both createRelease() calls run truly concurrently, which this test doesn't verify.

Fix in CursorFix in Web

@andreiborza
andreiborza merged commit 5d19ec0 into v4Feb 23, 2026
23 checks passed
@andreiborza
andreiborza deleted the ab/cherry-pick-charly branch February 23, 2026 12:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@andreiborza@chargome
, '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

fix(v4/webpack): Deduplicate webpack deploys (#875) - #888

Merged
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly
Feb 23, 2026
Merged

fix(v4/webpack): Deduplicate webpack deploys (#875)#888
andreiborza merged 1 commit into
v4from
ab/cherry-pick-charly

Conversation

@andreiborza

@andreiborzaandreiborza commented Feb 23, 2026

Copy link
Copy Markdown
Member

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)

  • Added a module-level guard (Set keyed by release name) so newDeploy only fires once per release per process
  • Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected

closes#873

Backport of #875 to v4.

Next.js Vercel deploys were creating duplicate deploy records (one per webpack compiler: client, server, edge)
- Added a module-level guard (Set<string> keyed by release name) so newDeploy only fires once per release per process
- Only guards newDeploy — all other release operations (create, finalize, setCommits) are idempotent and unaffected
closes#873
@github-actions

github-actionsBot commented Feb 23, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

V4/Webpack


🤖 This preview updates automatically when you update the PR.

@cursorcursorBot left a comment

Copy link
Copy Markdown

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 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (options.release.deploy) {
if (options.release.deploy && !_deployedReleases.has(options.release.name)) {
await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);
_deployedReleases.add(options.release.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition in deploy deduplication guard

High Severity

The check-then-act pattern (has() check, then await, then add()) creates a race condition when multiple webpack compilers run concurrently. Both compilers can pass the has() check before either executes add(), causing duplicate deploy records—the exact bug this PR aims to fix. The deduplication requires the release name to be added to _deployedReleases before the await, not after.

Fix in CursorFix in Web

// Module-level guard to prevent duplicate deploy records when multiple bundler plugin
// instances run in the same process (e.g. Next.js creates separate webpack compilers
// for client, server, and edge). Keyed by release name.
const _deployedReleases = new Set<string>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unbounded Set growth in long-running processes

Low Severity

The _deployedReleases Set accumulates release names indefinitely without cleanup. Since release names typically use git SHAs or CI commit identifiers (changing with each build), the Set grows unbounded in long-running production build processes, causing a memory leak. While dev mode skips deploy creation, production CI/CD pipelines or continuous deployment systems could accumulate entries.

Fix in CursorFix in Web

);

await managerA.createRelease();
await managerB.createRelease();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests don't verify concurrent execution scenario

Medium Severity

The test "should not create duplicate deploy records across separate plugin instances" uses sequential await calls instead of Promise.all, so it doesn't actually test concurrent execution. The race condition in the deduplication logic would only manifest when both createRelease() calls run truly concurrently, which this test doesn't verify.

Fix in CursorFix in Web

@andreiborza
andreiborza merged commit 5d19ec0 into v4Feb 23, 2026
23 checks passed
@andreiborza
andreiborza deleted the ab/cherry-pick-charly branch February 23, 2026 12:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@andreiborza@chargome