Skip to content

Conversation

@gabrielmfern
Copy link
Member

@gabrielmfern gabrielmfern commented Oct 21, 2025

This adds in a new directory integrations with a test file integrations.spec.ts that runs over the two integrations integrations/nextjs and integrations/esbuild respectively to make sure we don't introduce regressions that cause #625 or #587 respectively.

To actually get this to work reliably, I had to make sure that @react-email/render was not accessible for esbuild or turbopack builds. To do that, because of standard module resolution traversing parent node_modules directories, the test moves the integration's directory into the developer's tmp directory.


Summary by cubic

Adds integration tests for Next.js (Turbopack) and esbuild to prevent bundler regressions when using the SDK. Tests build minimal apps in an isolated temp directory to avoid parent node_modules leaking (e.g., @react-email/render).

  • New Features
    • Added integrations folder with minimal Next.js app and esbuild project using Resend.
    • Vitest builds each app from a tmp copy; package.json is rewritten to depend on the local SDK path.
    • New scripts: test:integrations and integration:nextjs; tsconfig now includes integrations.

lucasfcosta and others added 30 commits October 21, 2025 09:11
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Carolina de Moraes Josephik <[email protected]>
Co-authored-by: Carolina de Moraes Josephik <[email protected]>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Lucas da Costa <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Vitor Capretz <[email protected]>
Co-authored-by: Gabriel Miranda <[email protected]>
Co-authored-by: Vitor Capretz <[email protected]>
Co-authored-by: Cassio Zen <[email protected]>
Co-authored-by: Bu Kinoshita <[email protected]>
Co-authored-by: Lucas da Costa <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Vitor Capretz <[email protected]>
Co-authored-by: Gabriel Miranda <[email protected]>
Co-authored-by: Ty Mick <[email protected]>
Co-authored-by: Isabella Aquino <[email protected]>
Co-authored-by: Alexandre Cisneiros <[email protected]>
Co-authored-by: Carolina de Moraes Josephik <[email protected]>
Co-authored-by: Carolina de Moraes Josephik <[email protected]>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Vitor Capretz <[email protected]>
Co-authored-by: Cassio Zen <[email protected]>
Co-authored-by: Bu Kinoshita <[email protected]>
Co-authored-by: Zeno Rocha <[email protected]>
lucasfcosta and others added 22 commits October 21, 2025 14:48
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Carolina de Moraes Josephik <[email protected]>
Co-authored-by: Carolina de Moraes Josephik <[email protected]>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Lucas da Costa <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Vitor Capretz <[email protected]>
Co-authored-by: Gabriel Miranda <[email protected]>
Co-authored-by: Vitor Capretz <[email protected]>
Co-authored-by: Cassio Zen <[email protected]>
Co-authored-by: Bu Kinoshita <[email protected]>
Co-authored-by: Lucas da Costa <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Vitor Capretz <[email protected]>
Co-authored-by: Gabriel Miranda <[email protected]>
Co-authored-by: Ty Mick <[email protected]>
Co-authored-by: Isabella Aquino <[email protected]>
Co-authored-by: Alexandre Cisneiros <[email protected]>
Co-authored-by: Carolina de Moraes Josephik <[email protected]>
Co-authored-by: Carolina de Moraes Josephik <[email protected]>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Vitor Capretz <[email protected]>
Co-authored-by: Cassio Zen <[email protected]>
Co-authored-by: Bu Kinoshita <[email protected]>
Co-authored-by: Zeno Rocha <[email protected]>
);
testingLockPackageJson.dependencies.resend = sdkPath;
await fs.promises.writeFile(
path.resolve(temporaryIntegrationPath, 'package.json'),

Check failure

Code scanning / CodeQL

Insecure temporary file High test

Insecure creation of file in
the os temp dir
.

Copilot Autofix

AI 8 days ago

To securely create a temporary directory, use a well-established library like tmp, which ensures random directory names, exclusive creation, and appropriate permissions.
Steps:

  • Import tmp in the test file.
  • Instead of path.resolve(os.tmpdir(), ...), call tmp.dirSync() (or its async equivalent), which returns a unique, safely created temp directory path.
  • Remove the current logic for custom temp dir paths and creation checks—let tmp handle creation and permissions.
  • Use that directory as the base for all test operations (copying, modifying the package).

Required changes:

  • Add import tmp from 'tmp'; near the top.
  • In prepareTemporaryIntegrationCopy, replace the explicit construction of temporaryIntegrationPath, its manual deletion, and the explicit mkdir with a single tmp.dirSync() call.
  • Update all subsequent operations that use temporaryIntegrationPath as needed.

Suggested changeset 2
integrations/integrations.spec.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/integrations/integrations.spec.ts b/integrations/integrations.spec.ts
--- a/integrations/integrations.spec.ts
+++ b/integrations/integrations.spec.ts
@@ -2,6 +2,7 @@
 import fs from 'node:fs';
 import os from 'node:os';
 import path from 'node:path';
+import tmp from 'tmp';
 
 describe('integrations', () => {
   const sdkPath = path.resolve(__dirname, '..');
@@ -23,17 +24,9 @@
    * Also modifies the package.json to point to the SDK with an absolute path.
    */
   async function prepareTemporaryIntegrationCopy(integrationPath: string) {
-    const temporaryIntegrationPath = path.resolve(
-      os.tmpdir(),
-      `resend-node-integration-${path.basename(integrationPath)}`,
-    );
-    if (fs.existsSync(temporaryIntegrationPath)) {
-      await fs.promises.rm(temporaryIntegrationPath, {
-        recursive: true,
-        force: true,
-      });
-    }
-    await fs.promises.mkdir(temporaryIntegrationPath, { recursive: true });
+    // Securely create a unique temporary directory
+    const { name: temporaryIntegrationPath } = tmp.dirSync({ unsafeCleanup: true });
+
     await fs.promises.cp(
       path.resolve(__dirname, integrationPath),
       temporaryIntegrationPath,
EOF
@@ -2,6 +2,7 @@
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import tmp from 'tmp';

describe('integrations', () => {
const sdkPath = path.resolve(__dirname, '..');
@@ -23,17 +24,9 @@
* Also modifies the package.json to point to the SDK with an absolute path.
*/
async function prepareTemporaryIntegrationCopy(integrationPath: string) {
const temporaryIntegrationPath = path.resolve(
os.tmpdir(),
`resend-node-integration-${path.basename(integrationPath)}`,
);
if (fs.existsSync(temporaryIntegrationPath)) {
await fs.promises.rm(temporaryIntegrationPath, {
recursive: true,
force: true,
});
}
await fs.promises.mkdir(temporaryIntegrationPath, { recursive: true });
// Securely create a unique temporary directory
const { name: temporaryIntegrationPath } = tmp.dirSync({ unsafeCleanup: true });

await fs.promises.cp(
path.resolve(__dirname, integrationPath),
temporaryIntegrationPath,
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -49,7 +49,8 @@
   },
   "homepage": "https://github.com/resend/resend-node#readme",
   "dependencies": {
-    "svix": "1.76.1"
+    "svix": "1.76.1",
+    "tmp": "^0.2.5"
   },
   "peerDependencies": {
     "@react-email/render": "*"
EOF
@@ -49,7 +49,8 @@
},
"homepage": "https://github.com/resend/resend-node#readme",
"dependencies": {
"svix": "1.76.1"
"svix": "1.76.1",
"tmp": "^0.2.5"
},
"peerDependencies": {
"@react-email/render": "*"
This fix introduces these dependencies
Package Version Security advisories
tmp (npm) 0.2.5 None
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 12 files

Prompt for AI agents (all 2 issues)

Understand the root cause of the following 2 issues and fix them.


<file name="integrations/integrations.spec.ts">

<violation number="1" location="integrations/integrations.spec.ts:73">
The esbuild integration test throws an error saying &quot;next.js build failed&quot;, so an esbuild failure would surface with the wrong integration name, making it harder to triage.</violation>
</file>

<file name="integrations/nextjs/app/route.js">

<violation number="1" location="integrations/nextjs/app/route.js:3">
Rule violated: **Initialisms and Acronyms Naming Conventions**

Rename the `GET` handler to use camelCase/PascalCase to comply with the initialism casing convention.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

},
);
if (buildInstall.status !== 0) {
throw new Error('next.js build failed');
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

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

The esbuild integration test throws an error saying "next.js build failed", so an esbuild failure would surface with the wrong integration name, making it harder to triage.

Prompt for AI agents
Address the following comment on integrations/integrations.spec.ts at line 73:

<comment>The esbuild integration test throws an error saying &quot;next.js build failed&quot;, so an esbuild failure would surface with the wrong integration name, making it harder to triage.</comment>

<file context>
@@ -0,0 +1,93 @@
+      },
+    );
+    if (buildInstall.status !== 0) {
+      throw new Error(&#39;next.js build failed&#39;);
+    }
+  });
</file context>
Suggested change
throw new Error('next.js build failed');
throw new Error('esbuild build failed');
Fix with Cubic

@@ -0,0 +1,7 @@
import { Resend } from 'resend';

export function GET() {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

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

Rule violated: Initialisms and Acronyms Naming Conventions

Rename the GET handler to use camelCase/PascalCase to comply with the initialism casing convention.

Prompt for AI agents
Address the following comment on integrations/nextjs/app/route.js at line 3:

<comment>Rename the `GET` handler to use camelCase/PascalCase to comply with the initialism casing convention.</comment>

<file context>
@@ -0,0 +1,7 @@
+import { Resend } from &#39;resend&#39;;
+
+export function GET() {
+  new Resend(&#39;&#39;);
+
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants