Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ vercel.json @getsentry/owners-js-bu
/.github/file-filters.yml @getsentry/owners-js-build
babel.config.* @getsentry/owners-js-build
build-utils/ @getsentry/owners-js-build
eslint.config.mjs @getsentry/owners-js-build
eslint.config.js @getsentry/owners-js-build
jest-balance.json @getsentry/owners-js-build
jest.config.ts @getsentry/owners-js-build
tsconfig.* @getsentry/owners-js-build
Expand Down
58 changes: 28 additions & 30 deletions .github/workflows/scripts/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,35 @@
*
*/

module.exports = {
/**
* Checks what files were changed in a commit and adds a GH check
* corresponding with changes. This can be used by our deploy system to
* determine what Freight deploy we can use.
*/
updateChangeType: async ({github, context, fileChanges}) => {
// Note that `fileChanges` bools and ints will get cast to strings
const {frontend_all: frontend, backend_all: backend} = fileChanges;
const frontendOnly = frontend === 'true' && backend === 'false';
const backendOnly = backend === 'true' && frontend === 'false';
/**
* Checks what files were changed in a commit and adds a GH check
* corresponding with changes. This can be used by our deploy system to
* determine what Freight deploy we can use.
*/
export async function updateChangeType({github, context, fileChanges}) {
// Note that `fileChanges` bools and ints will get cast to strings
const {frontend_all: frontend, backend_all: backend} = fileChanges;
const frontendOnly = frontend === 'true' && backend === 'false';
const backendOnly = backend === 'true' && frontend === 'false';

const name = frontendOnly
? 'only frontend changes'
: backendOnly
? 'only backend changes'
: 'fullstack changes';
const name = frontendOnly
? 'only frontend changes'
: backendOnly
? 'only backend changes'
: 'fullstack changes';

if (!name) {
return null;
}
if (!name) {
return null;
}

const result = await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name,
head_sha: context.sha,
status: 'completed',
conclusion: 'success',
});
const result = await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name,
head_sha: context.sha,
status: 'completed',
conclusion: 'success',
});

return result;
},
};
return result;
}
54 changes: 26 additions & 28 deletions .github/workflows/scripts/getsentry-dispatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,34 @@ const DISPATCHES = [
},
];

module.exports = {
dispatch: async ({github, context, core, fileChanges, mergeCommitSha}) => {
core.startGroup('Dispatching request to getsentry.');
export async function dispatch({github, context, core, fileChanges, mergeCommitSha}) {
core.startGroup('Dispatching request to getsentry.');

await Promise.all(
DISPATCHES.map(({workflow, pathFilterName}) => {
const inputs = {
pull_request_number: `${context.payload.pull_request.number}`, // needs to be string
skip: `${fileChanges[pathFilterName] !== 'true'}`, // even though this is a boolean, it must be cast to a string
await Promise.all(
DISPATCHES.map(({workflow, pathFilterName}) => {
const inputs = {
pull_request_number: `${context.payload.pull_request.number}`, // needs to be string
skip: `${fileChanges[pathFilterName] !== 'true'}`, // even though this is a boolean, it must be cast to a string

// sentrySHA is the sha getsentry should run against.
'sentry-sha': mergeCommitSha,
// prSHA is the sha actions should post commit statuses too.
'sentry-pr-sha': context.payload.pull_request.head.sha,
};
// sentrySHA is the sha getsentry should run against.
'sentry-sha': mergeCommitSha,
// prSHA is the sha actions should post commit statuses too.
'sentry-pr-sha': context.payload.pull_request.head.sha,
};

core.info(
`Sending dispatch for '${workflow}':\n${JSON.stringify(inputs, null, 2)}`
);
core.info(
`Sending dispatch for '${workflow}':\n${JSON.stringify(inputs, null, 2)}`
);

return github.rest.actions.createWorkflowDispatch({
owner: 'getsentry',
repo: 'getsentry',
workflow_id: workflow,
ref: 'master',
inputs,
});
})
);
return github.rest.actions.createWorkflowDispatch({
owner: 'getsentry',
repo: 'getsentry',
workflow_id: workflow,
ref: 'master',
inputs,
});
})
);

core.endGroup();
},
};
core.endGroup();
}
6 changes: 1 addition & 5 deletions .github/workflows/scripts/wait-for-merge-commit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ function wait(interval) {
});
}

async function waitForMergeCommit({github, context, core}) {
export async function waitForMergeCommit({github, context, core}) {
const pullRequest = context.payload.pull_request;
const pullNumber = pullRequest.number;

Expand Down Expand Up @@ -58,7 +58,3 @@ async function waitForMergeCommit({github, context, core}) {
core.setFailed(`PR #${pullNumber} is not mergeable`);
}
}

module.exports = {
waitForMergeCommit,
};
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
"python.testing.pytestPath": "${workspaceFolder}/.venv/bin/pytest",
"python.testing.pytestArgs": ["tests"],
"python.analysis.autoImportCompletions": true,
"prettier.configPath": "prettier.config.mjs",
"prettier.configPath": "prettier.config.js",
"biome.enabled": false,
"cursorpyright.analysis.autoImportCompletions": true,
"mypy-type-checker.path": ["${workspaceFolder}/.venv/bin/mypy"],
Expand Down
33 changes: 11 additions & 22 deletions eslint.config.mjs → eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ import invariant from 'invariant';
import typescript from 'typescript-eslint';

// eslint-disable-next-line boundaries/element-types
import * as sentryScrapsPlugin from './static/eslint/eslintPluginScraps/index.mjs';
import * as sentryScrapsPlugin from './static/eslint/eslintPluginScraps/index.js';
// eslint-disable-next-line boundaries/element-types
import * as sentryPlugin from './static/eslint/eslintPluginSentry/index.mjs';
import * as sentryPlugin from './static/eslint/eslintPluginSentry/index.js';

invariant(react.configs.flat, 'For typescript');
invariant(react.configs.flat.recommended, 'For typescript');
Expand Down Expand Up @@ -238,7 +238,7 @@ export default typescript.config([
name: 'eslint/global/files',
// Default file selection
// https://eslint.org/docs/latest/use/configure/configuration-files#specifying-files-and-ignores
files: ['**/*.js', '**/*.mjs', '**/*.ts', '**/*.jsx', '**/*.tsx'],
files: ['**/*.js', '**/*.ts', '**/*.jsx', '**/*.tsx'],
},
// Global ignores
// https://eslint.org/docs/latest/use/configure/configuration-files#globally-ignoring-files-with-ignores
Expand Down Expand Up @@ -407,7 +407,6 @@ export default typescript.config([
block: {exceptions: ['*'], balanced: true},
},
],
strict: 'error',
'vars-on-top': 'off',
'wrap-iife': ['error', 'any'],
yoda: 'error',
Expand All @@ -432,7 +431,7 @@ export default typescript.config([
'import/no-duplicates': 'error',
'import/no-extraneous-dependencies': [
'error',
{includeTypes: true, devDependencies: ['!eslint.config.mjs']},
{includeTypes: true, devDependencies: ['!eslint.config.js']},
],
'import/no-named-default': 'error',
'import/no-nodejs-modules': 'error',
Expand Down Expand Up @@ -849,10 +848,7 @@ export default typescript.config([
name: 'files/*.config.*',
files: ['**/*.config.*'],
languageOptions: {
globals: {
...globals.commonjs,
...globals.node,
},
globals: globals.node,
},

rules: {
Expand All @@ -861,11 +857,9 @@ export default typescript.config([
},
{
name: 'eslint',
files: ['static/eslint/**/*.mjs'],
files: ['static/eslint/**/*.js'],
languageOptions: {
globals: {
...globals.node,
},
globals: globals.node,
},

rules: {
Expand All @@ -877,11 +871,8 @@ export default typescript.config([
name: 'files/scripts',
files: ['scripts/**/*.{js,ts}', 'tests/js/test-balancer/index.js'],
languageOptions: {
sourceType: 'commonjs',
globals: {
...globals.commonjs,
...globals.node,
},
sourceType: 'module',
globals: globals.node,
},
rules: {
'no-console': 'off',
Expand All @@ -898,10 +889,8 @@ export default typescript.config([
'tests/js/setup.ts',
],
languageOptions: {
sourceType: 'commonjs',
globals: {
...globals.commonjs,
},
sourceType: 'module',
globals: globals.node,
},
rules: {
'import/no-nodejs-modules': 'off',
Expand Down
1 change: 0 additions & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,6 @@ const config: Config.InitialOptions = {
transform: {
'^.+\\.jsx?$': ['babel-jest', babelConfig as any],
'^.+\\.tsx?$': ['babel-jest', babelConfig as any],
'^.+\\.mjs?$': ['babel-jest', babelConfig as any],
'^.+\\.pegjs?$': '<rootDir>/tests/js/jest-pegjs-transform.js',
},
transformIgnorePatterns: [
Expand Down
26 changes: 13 additions & 13 deletions knip.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const productionEntryPoints = [
'static/app/utils/statics-setup.tsx',
'static/app/views/integrationPipeline/index.tsx',
// very dynamically imported
'static/app/gettingStartedDocs/**/*.{js,mjs,ts,tsx}',
'static/app/gettingStartedDocs/**/*.{js,ts,tsx}',
// this is imported with require.context
'static/app/data/forms/*.tsx',
// --- we should be able to get rid of those: ---
Expand All @@ -24,14 +24,14 @@ const productionEntryPoints = [
// Prevent exception until we build out coverage
'static/app/components/prevent/virtualRenderers/**/*.{js,ts,tsx}',
// todo we currently keep all icons
'static/app/icons/**/*.{js,mjs,ts,tsx}',
'static/app/icons/**/*.{js,ts,tsx}',
// todo find out how chartcuterie works
'static/app/chartcuterie/**/*.{js,mjs,ts,tsx}',
'static/app/chartcuterie/**/*.{js,ts,tsx}',
];

const testingEntryPoints = [
'static/**/*.spec.{js,mjs,ts,tsx}',
'tests/js/**/*.spec.{js,mjs,ts,tsx}',
'static/**/*.spec.{js,ts,tsx}',
'tests/js/**/*.spec.{js,ts,tsx}',
// jest uses this
'tests/js/test-balancer/index.js',
];
Expand All @@ -40,7 +40,7 @@ const storyBookEntryPoints = [
// our storybook implementation is here
'static/app/stories/storybook.tsx',
'static/app/stories/playground/*.tsx',
'static/**/*.stories.{js,mjs,ts,tsx}',
'static/**/*.stories.{js,ts,tsx}',
'static/**/*.mdx',
];

Expand All @@ -49,23 +49,23 @@ const config: KnipConfig = {
...productionEntryPoints.map(entry => `${entry}!`),
...testingEntryPoints,
...storyBookEntryPoints,
'static/eslint/**/index.mjs',
'static/eslint/**/index.js',
// figma code connect files - consumed by Figma CLI
'static/**/*.figma.{tsx,jsx}',
],
project: [
'static/**/*.{js,mjs,ts,tsx}!',
'static/**/*.{js,ts,tsx}!',
'config/**/*.ts',
'tests/js/**/*.{js,mjs,ts,tsx}',
'tests/js/**/*.{js,ts,tsx}',
// fixtures can be ignored in production - it's fine that they are only used in tests
'!static/**/{fixtures,__fixtures__}/**!',
// helper files for tests - it's fine that they are only used in tests
'!static/**/*{t,T}estUtils*.{js,mjs,ts,tsx}!',
'!static/**/*{t,T}estUtils*.{js,ts,tsx}!',
// helper files for stories - it's fine that they are only used in tests
'!static/app/**/__stories__/*.{js,mjs,ts,tsx}!',
'!static/app/stories/**/*.{js,mjs,ts,tsx}!',
'!static/app/**/__stories__/*.{js,ts,tsx}!',
'!static/app/stories/**/*.{js,ts,tsx}!',
// ignore eslint plugins in production
'!static/eslint/**/*.mjs!',
'!static/eslint/**/*.js!',
],
compilers: {
mdx: async text => String(await compile(text)),
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"$schema": "https://json.schemastore.org/package.json",
"name": "sentry",
"version": "0.0.0",
"type": "module",
"private": true,
"repository": {
"type": "git",
Expand Down Expand Up @@ -268,10 +269,10 @@
"lint": "pnpm run lint:prettier && pnpm run lint:js && pnpm run lint:css",
"lint:js": "eslint --concurrency=3",
"lint:css": "stylelint '**/*.[jt]sx'",
"lint:prettier": "prettier \"**/*{.md,.yaml,.js,.mjs,.jsx,.ts,.tsx}\" --check --log-level=error --experimental-cli --no-cache",
"lint:prettier": "prettier \"**/*{.md,.yaml,.js,.jsx,.ts,.tsx}\" --check --log-level=error --experimental-cli --no-cache",
"fix": "pnpm run fix:prettier && pnpm run fix:eslint",
"fix:eslint": "eslint --fix",
"fix:prettier": "prettier \"**/*{.md,.yaml,.js,.mjs,.jsx,.ts,.tsx}\" --write --log-level=error --experimental-cli --no-cache",
"fix:prettier": "prettier \"**/*{.md,.yaml,.js,.jsx,.ts,.tsx}\" --write --log-level=error --experimental-cli --no-cache",
"dev": "pnpm install --frozen-lockfile && sentry devserver",
"dev-ui": "NODE_OPTIONS='--experimental-transform-types' SENTRY_UI_DEV_ONLY=1 SENTRY_WEBPACK_PROXY_PORT=7999 SENTRY_UI_HOT_RELOAD=1 rspack serve",
"dev-ui-production": "NODE_OPTIONS='--experimental-transform-types' NODE_ENV=production SENTRY_UI_DEV_ONLY=1 SENTRY_WEBPACK_PROXY_PORT=7999 SENTRY_UI_HOT_RELOAD=1 rspack --mode production serve",
Expand Down
File renamed without changes.
5 changes: 3 additions & 2 deletions scripts/extract-android-device-names.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use strict';

import fs from 'node:fs';

// @ts-expect-error csv-parser has no types
const csv = require('csv-parser');
const fs = require('node:fs');
import csv from 'csv-parser';

/**
* Transform CSV results into device mapping object
Expand Down
4 changes: 2 additions & 2 deletions scripts/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';
import {run} from 'jest';
Copy link
Contributor

Choose a reason for hiding this comment

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

ESM import hoisting defeats env var initialization order

Low Severity

The static import {run} from 'jest' on line 1 is hoisted and evaluated before the process.env assignments on lines 5–7. In the original CJS version, require('jest') was called at the end of the file (after all env setup), matching the comment "Do this as the first thing so that any code reading it knows the right env." Now the jest module (and its transitive dependencies) loads before NODE_ENV, TZ, etc. are set, and the unhandledRejection handler is also registered after the import. A dynamic await import('jest') or moving the env setup to a separate preloaded module would preserve the original execution order.

Fix in Cursor Fix in Web

Copy link
Member Author

@JoshuaKGoldberg JoshuaKGoldberg Feb 27, 2026

Choose a reason for hiding this comment

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

I don't think this matters? Jest always runs in test mode, and PUBLIC_URL & TZ are Sentry - only constructs that I know of.


// Do this as the first thing so that any code reading it knows the right env.
// process.env.BABEL_ENV = 'test';
Expand All @@ -20,4 +20,4 @@ if (process.env.CI || process.env.SENTRY_PRECOMMIT || argv.includes('--coverage'
argv = argv.filter(arg => arg !== '--watch');
}

require('jest').run(argv);
run(argv);
2 changes: 1 addition & 1 deletion static/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
- `package.json`: Node.js dependencies and scripts
- `rspack.config.ts`: Frontend build configuration
- `tsconfig.json`: TypeScript configuration
- `eslint.config.mjs`: ESLint configuration
- `eslint.config.js`: ESLint configuration
- `stylelint.config.js`: CSS/styling linting
- **Components**: `static/app/components/{component}/`
- **Views**: `static/app/views/{area}/{page}.tsx`
Expand Down
1 change: 1 addition & 0 deletions static/eslint/eslintPluginScraps/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {rules} from './src/rules/index.js';
1 change: 0 additions & 1 deletion static/eslint/eslintPluginScraps/index.mjs

This file was deleted.

Loading
Loading