Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .craft.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ preReleaseCommand: bash scripts/craft-pre-release.sh
targets:
# NPM Targets
## 1. Base Packages, node or browser SDKs depend on
## 1.1 Types
- name: npm
id: '@sentry/types'
includeNames: /^sentry-types-\d.*\.tgz$/
## 1.2 Core SDKs
## 1.1 Core SDKs
- name: npm
id: '@sentry/core'
includeNames: /^sentry-core-\d.*\.tgz$/
## 1.2 Types
- name: npm
id: '@sentry/types'
includeNames: /^sentry-types-\d.*\.tgz$/
- name: npm
id: '@sentry/node-core'
includeNames: /^sentry-node-core-\d.*\.tgz$/
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
steps:
- name: Get auth token
id: token
uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0
with:
app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }}
private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }}
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,8 @@ jobs:
working-directory: ${{ runner.temp }}/test-application
timeout-minutes: 7
run: ${{ matrix.build-command || 'pnpm test:build' }}
env:
SENTRY_E2E_WORKSPACE_ROOT: ${{ github.workspace }}

- name: Install Playwright
uses: ./.github/actions/install-playwright
Expand All @@ -1003,6 +1005,8 @@ jobs:
working-directory: ${{ runner.temp }}/test-application
timeout-minutes: 10
run: ${{ matrix.assert-command || 'pnpm test:assert' }}
env:
SENTRY_E2E_WORKSPACE_ROOT: ${{ github.workspace }}

- name: Upload Playwright Traces
uses: actions/upload-artifact@v5
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/create-issue-for-unreferenced-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ jobs:
return;
}
// Bail if this edit was made by the GitHub Actions bot (this workflow)
// This prevents infinite loops when we update the PR body with the new issue reference
// We check login specifically to not skip edits from other legitimate bots
if (context.payload.sender && context.payload.sender.login === 'github-actions[bot]') {
console.log(`PR #${pr.number} was edited by github-actions[bot] (this workflow), skipping.`);
return;
}
// Check if the PR is already approved
const reviewsResponse = await github.rest.pulls.listReviews({
owner: context.repo.owner,
Expand Down Expand Up @@ -109,7 +117,7 @@ jobs:
console.log(`Created issue #${issueID}.`);
// Update the PR body to reference the new issue
const updatedPrBody = `${prBody}\n\nCloses #${issueID}`;
const updatedPrBody = `${prBody}\n\nCloses #${issueID} (added automatically)`;
await github.rest.pulls.update({
owner: context.repo.owner,
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
steps:
- name: Get auth token
id: token
uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0
with:
app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }}
private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }}
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,28 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

## 10.30.0

- feat(nextjs): Deprecate Webpack top-level options ([#18343](https://github.com/getsentry/sentry-javascript/pull/18343))
- feat(node): Capture scope when event loop blocked ([#18040](https://github.com/getsentry/sentry-javascript/pull/18040))
- fix(aws-serverless): Remove hyphens from AWS-lambda origins ([#18353](https://github.com/getsentry/sentry-javascript/pull/18353))
- fix(core): Parse method from Request object in fetch ([#18453](https://github.com/getsentry/sentry-javascript/pull/18453))
- fix(react): Add transaction name guards for rapid lazy-route navigations ([#18346](https://github.com/getsentry/sentry-javascript/pull/18346))

<details>
<summary> <strong>Internal Changes</strong> </summary>

- chore(ci): Fix double issue creation for unreferenced PRs ([#18442](https://github.com/getsentry/sentry-javascript/pull/18442))
- chore(deps): bump next from 15.5.4 to 15.5.7 in /dev-packages/e2e-tests/test-applications/nextjs-15 ([#18411](https://github.com/getsentry/sentry-javascript/pull/18411))
- chore(deps): bump next from 15.5.4 to 15.5.7 in /dev-packages/e2e-tests/test-applications/nextjs-15-intl ([#18400](https://github.com/getsentry/sentry-javascript/pull/18400))
- chore(deps): bump next from 16.0.0 to 16.0.7 in /dev-packages/e2e-tests/test-applications/nextjs-16 ([#18399](https://github.com/getsentry/sentry-javascript/pull/18399))
- chore(deps): bump next from 16.0.0 to 16.0.7 in /dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents ([#18427](https://github.com/getsentry/sentry-javascript/pull/18427))
- chore(deps): bump next from 16.0.0 to 16.0.7 in /dev-packages/e2e-tests/test-applications/nextjs-16-tunnel ([#18439](https://github.com/getsentry/sentry-javascript/pull/18439))
- chore(publish): Fix publish order for `@sentry/types` ([#18429](https://github.com/getsentry/sentry-javascript/pull/18429))
- ci(deps): bump actions/create-github-app-token from 2.1.4 to 2.2.0 ([#18362](https://github.com/getsentry/sentry-javascript/pull/18362))

</details>

## 10.29.0

### Important Changes
Expand Down
2 changes: 2 additions & 0 deletions dev-packages/e2e-tests/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ async function run(): Promise<void> {
REACT_APP_E2E_TEST_DSN: dsn,
E2E_TEST_SENTRY_ORG_SLUG: process.env.E2E_TEST_SENTRY_ORG_SLUG || DEFAULT_SENTRY_ORG_SLUG,
E2E_TEST_SENTRY_PROJECT: process.env.E2E_TEST_SENTRY_PROJECT || DEFAULT_SENTRY_PROJECT,
// Pass workspace root so tests copied to temp dirs can find local packages
SENTRY_E2E_WORKSPACE_ROOT: resolve(__dirname, '../..'),
};

const env = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ const LAYER_DIR = './node_modules/@sentry/aws-serverless/';
const DEFAULT_NODE_VERSION = '22';
export const SAM_PORT = 3001;

function resolvePackagesDir(): string {
// When running via the e2e test runner, tests are copied to a temp directory
// so we need the workspace root passed via env var
const workspaceRoot = process.env.SENTRY_E2E_WORKSPACE_ROOT;
if (workspaceRoot) {
return path.join(workspaceRoot, 'packages');
}
// Fallback for local development when running from the original location
return path.resolve(__dirname, '../../../../../packages');
}

export class LocalLambdaStack extends Stack {
sentryLayer: CfnResource;

Expand Down Expand Up @@ -67,10 +78,48 @@ export class LocalLambdaStack extends Stack {
const functionName = `${addLayer ? 'Layer' : 'Npm'}${lambdaDir}`;

if (!addLayer) {
const lambdaPath = path.resolve(functionsDir, lambdaDir);
const packageLockPath = path.join(lambdaPath, 'package-lock.json');
const nodeModulesPath = path.join(lambdaPath, 'node_modules');

// Point the dependency at the locally built packages so tests use the current workspace bits
// We need to link all @sentry/* packages that are dependencies of aws-serverless
// because otherwise npm will try to install them from the registry, where the current version is not yet published
const packagesToLink = ['aws-serverless', 'node', 'core', 'node-core', 'opentelemetry'];
const dependencies: Record<string, string> = {};

const packagesDir = resolvePackagesDir();
for (const pkgName of packagesToLink) {
const pkgDir = path.join(packagesDir, pkgName);
if (!fs.existsSync(pkgDir)) {
throw new Error(
`[LocalLambdaStack] Workspace package ${pkgName} not found at ${pkgDir}. Did you run the build?`,
);
}
const relativePath = path.relative(lambdaPath, pkgDir);
dependencies[`@sentry/${pkgName}`] = `file:${relativePath.replace(/\\/g, '/')}`;
}

console.log(`[LocalLambdaStack] Install dependencies for ${functionName}`);
const packageJson = { dependencies: { '@sentry/aws-serverless': '* || latest' } };
fs.writeFileSync(path.join(functionsDir, lambdaDir, 'package.json'), JSON.stringify(packageJson, null, 2));
execFileSync('npm', ['install', '--prefix', path.join(functionsDir, lambdaDir)], { stdio: 'inherit' });

if (fs.existsSync(packageLockPath)) {
// Prevent stale lock files from pinning the published package version
fs.rmSync(packageLockPath);
}

if (fs.existsSync(nodeModulesPath)) {
// Ensure we reinstall from the workspace instead of reusing cached dependencies
fs.rmSync(nodeModulesPath, { recursive: true, force: true });
}

const packageJson = {
dependencies,
};

fs.writeFileSync(path.join(lambdaPath, 'package.json'), JSON.stringify(packageJson, null, 2));
// Use --install-links to copy files instead of creating symlinks for file: dependencies.
// Symlinks don't work inside the Docker container because the target paths don't exist there.
execFileSync('npm', ['install', '--install-links', '--prefix', lambdaPath], { stdio: 'inherit' });
}

new CfnResource(this, functionName, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const test = base.extend<{ testEnvironment: LocalLambdaStack; lambdaClien
console.log('[testEnvironment fixture] Setting up AWS Lambda test infrastructure');

execSync('docker network prune -f');
execSync(`docker network create --driver bridge ${DOCKER_NETWORK_NAME}`);
createDockerNetwork();

const hostIp = await getHostIp();
const app = new App();
Expand Down Expand Up @@ -71,6 +71,8 @@ export const test = base.extend<{ testEnvironment: LocalLambdaStack; lambdaClien
resolve(void 0);
}, 5000);
});

removeDockerNetwork();
}
},
{ scope: 'worker', auto: true },
Expand All @@ -88,3 +90,27 @@ export const test = base.extend<{ testEnvironment: LocalLambdaStack; lambdaClien
await use(lambdaClient);
},
});

function createDockerNetwork() {
try {
execSync(`docker network create --driver bridge ${DOCKER_NETWORK_NAME}`);
} catch (error) {
const stderr = (error as { stderr?: Buffer }).stderr?.toString() ?? '';
if (stderr.includes('already exists')) {
console.log(`[testEnvironment fixture] Reusing existing docker network ${DOCKER_NETWORK_NAME}`);
return;
}
throw error;
}
}

function removeDockerNetwork() {
try {
execSync(`docker network rm ${DOCKER_NETWORK_NAME}`);
} catch (error) {
const stderr = (error as { stderr?: Buffer }).stderr?.toString() ?? '';
if (!stderr.includes('No such network')) {
console.warn(`[testEnvironment fixture] Failed to remove docker network ${DOCKER_NETWORK_NAME}: ${stderr}`);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test.describe('Lambda layer', () => {
data: {
'sentry.sample_rate': 1,
'sentry.source': 'custom',
'sentry.origin': 'auto.otel.aws-lambda',
'sentry.origin': 'auto.otel.aws_lambda',
'sentry.op': 'function.aws.lambda',
'cloud.account.id': '012345678912',
'faas.execution': expect.any(String),
Expand All @@ -32,7 +32,7 @@ test.describe('Lambda layer', () => {
'otel.kind': 'SERVER',
},
op: 'function.aws.lambda',
origin: 'auto.otel.aws-lambda',
origin: 'auto.otel.aws_lambda',
span_id: expect.stringMatching(/[a-f0-9]{16}/),
status: 'ok',
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
Expand Down Expand Up @@ -91,7 +91,7 @@ test.describe('Lambda layer', () => {
data: {
'sentry.sample_rate': 1,
'sentry.source': 'custom',
'sentry.origin': 'auto.otel.aws-lambda',
'sentry.origin': 'auto.otel.aws_lambda',
'sentry.op': 'function.aws.lambda',
'cloud.account.id': '012345678912',
'faas.execution': expect.any(String),
Expand All @@ -100,7 +100,7 @@ test.describe('Lambda layer', () => {
'otel.kind': 'SERVER',
},
op: 'function.aws.lambda',
origin: 'auto.otel.aws-lambda',
origin: 'auto.otel.aws_lambda',
span_id: expect.stringMatching(/[a-f0-9]{16}/),
status: 'ok',
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
Expand Down Expand Up @@ -214,7 +214,7 @@ test.describe('Lambda layer', () => {
data: {
'sentry.sample_rate': 1,
'sentry.source': 'custom',
'sentry.origin': 'auto.otel.aws-lambda',
'sentry.origin': 'auto.otel.aws_lambda',
'sentry.op': 'function.aws.lambda',
'cloud.account.id': '012345678912',
'faas.execution': expect.any(String),
Expand All @@ -223,7 +223,7 @@ test.describe('Lambda layer', () => {
'otel.kind': 'SERVER',
},
op: 'function.aws.lambda',
origin: 'auto.otel.aws-lambda',
origin: 'auto.otel.aws_lambda',
span_id: expect.stringMatching(/[a-f0-9]{16}/),
status: 'ok',
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test.describe('NPM package', () => {
data: {
'sentry.sample_rate': 1,
'sentry.source': 'custom',
'sentry.origin': 'auto.otel.aws-lambda',
'sentry.origin': 'auto.otel.aws_lambda',
'sentry.op': 'function.aws.lambda',
'cloud.account.id': '012345678912',
'faas.execution': expect.any(String),
Expand All @@ -32,7 +32,7 @@ test.describe('NPM package', () => {
'otel.kind': 'SERVER',
},
op: 'function.aws.lambda',
origin: 'auto.otel.aws-lambda',
origin: 'auto.otel.aws_lambda',
span_id: expect.stringMatching(/[a-f0-9]{16}/),
status: 'ok',
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
Expand Down Expand Up @@ -91,7 +91,7 @@ test.describe('NPM package', () => {
data: {
'sentry.sample_rate': 1,
'sentry.source': 'custom',
'sentry.origin': 'auto.otel.aws-lambda',
'sentry.origin': 'auto.otel.aws_lambda',
'sentry.op': 'function.aws.lambda',
'cloud.account.id': '012345678912',
'faas.execution': expect.any(String),
Expand All @@ -100,7 +100,7 @@ test.describe('NPM package', () => {
'otel.kind': 'SERVER',
},
op: 'function.aws.lambda',
origin: 'auto.otel.aws-lambda',
origin: 'auto.otel.aws_lambda',
span_id: expect.stringMatching(/[a-f0-9]{16}/),
status: 'ok',
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@types/node": "^18.19.1",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.9",
"next": "15.5.4",
"next": "15.5.7",
"next-intl": "^4.3.12",
"react": "latest",
"react-dom": "latest",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@types/react": "18.0.26",
"@types/react-dom": "18.0.9",
"ai": "^3.0.0",
"next": "15.5.4",
"next": "15.5.7",
"react": "latest",
"react-dom": "latest",
"typescript": "~5.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@sentry/nextjs": "latest || *",
"@sentry/core": "latest || *",
"import-in-the-middle": "^1",
"next": "16.0.0",
"next": "16.0.7",
"react": "19.1.0",
"react-dom": "19.1.0",
"require-in-the-middle": "^7",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@sentry/core": "latest || *",
"ai": "^3.0.0",
"import-in-the-middle": "^1",
"next": "16.0.0",
"next": "16.0.7",
"react": "19.1.0",
"react-dom": "19.1.0",
"require-in-the-middle": "^7",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@sentry/core": "latest || *",
"ai": "^3.0.0",
"import-in-the-middle": "^2",
"next": "16.0.0",
"next": "16.0.7",
"react": "19.1.0",
"react-dom": "19.1.0",
"require-in-the-middle": "^8",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ const router = sentryCreateBrowserRouter(
lazyChildren: () => import('./pages/deep/Level1Routes').then(module => module.level2Routes),
},
},
{
path: '/slow-fetch',
handle: {
// This lazy handler takes 500ms due to the top-level await in SlowFetchLazyRoutes.tsx
// It also makes a fetch request during loading which creates a span
lazyChildren: () => import('./pages/SlowFetchLazyRoutes').then(module => module.slowFetchRoutes),
},
},
],
{
async patchRoutesOnNavigation({ matches, patch }: Parameters<PatchRoutesOnNavigationFunction>[0]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ const DelayedLazyRoute = () => {
Back Home
</Link>
<br />
<Link to="/slow-fetch/222" id="delayed-lazy-to-slow-fetch">
Go to Slow Fetch Route (500ms)
</Link>
<br />
<Link to="/another-lazy/sub" id="delayed-lazy-to-another-lazy">
Go to Another Lazy Route
</Link>
<br />
<Link to={`/delayed-lazy/${id}?view=detailed`} id="link-to-query-view-detailed">
View: Detailed (query param)
</Link>
Expand Down
Loading
Loading