Skip to content
Open
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
3 changes: 1 addition & 2 deletions packages/remix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@
"@sentry/core": "10.40.0",
"@sentry/node": "10.40.0",
"@sentry/react": "10.40.0",
"glob": "^10.3.4",
"yargs": "^17.6.0"
"glob": "^10.3.4"
},
"devDependencies": {
"@remix-run/node": "^2.17.4",
Expand Down
120 changes: 63 additions & 57 deletions packages/remix/scripts/sentry-upload-sourcemaps.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,74 @@
#!/usr/bin/env node
const yargs = require('yargs');
const { parseArgs } = require('node:util');
Copy link

Choose a reason for hiding this comment

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

Bug: The script uses util.parseArgs, which will crash on Node.js versions 18.0.0-18.2.x, despite the package.json allowing these versions.
Severity: MEDIUM

Suggested Fix

Update the package.json engines field to require "node": ">=18.3.0". Alternatively, add a runtime check for util.parseArgs and provide a helpful error message or a fallback implementation for older Node.js versions.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: packages/remix/scripts/sentry-upload-sourcemaps.js#L2

Potential issue: The `sentry-upload-sourcemaps.js` script utilizes the `util.parseArgs`
function, which is only available in Node.js versions 18.3.0 and later. The project's
`package.json` declares support for Node.js version 18.0.0 and above (`"node": ">=18"`).
Consequently, users running the script on Node.js versions between 18.0.0 and 18.2.x
will encounter a runtime crash because the `util.parseArgs` function does not exist in
their environment. The current CI setup does not test against these specific older patch
versions of Node 18, so this issue would not be caught automatically.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Member

Choose a reason for hiding this comment

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

Since our minimum is 18.0 we need to have a fallback for utils.parseArgs

Copy link
Member

@isaacs isaacs Feb 26, 2026

Choose a reason for hiding this comment

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

We could add @pkgjs/parseargs as a dependency instead of yargs, and keep that around until we drop v18 support. It's at least less of a cost than yargs, because it's much smaller.

Copy link
Member

@isaacs isaacs Feb 26, 2026

Choose a reason for hiding this comment

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

Suggested change
const { parseArgs } = require('node:util');
// TODO: remove when node v18 support drops
let parseArgs;
try {
parseArgs = require('node:util').parseArgs;
} catch {
parseArgs = require('@pkgjs/parseargs').parseArgs;
}


const { createRelease } = require('./createRelease');
const { injectDebugId } = require('./injectDebugId');

const DEFAULT_URL_PREFIX = '~/build/';
const DEFAULT_BUILD_PATH = 'public/build';

const argv = yargs(process.argv.slice(2))
.option('release', {
type: 'string',
describe:
'The release number\n' +
"If not provided, a new release id will be determined by Sentry CLI's `propose-version`.\n" +
'See: https://docs.sentry.io/product/releases/suspect-commits/#using-the-cli\n',
})
.option('org', {
type: 'string',
describe: 'The Sentry organization slug',
})
.option('project', {
type: 'string',
describe: 'The Sentry project slug',
})
.option('url', {
type: 'string',
describe: 'The Sentry server URL',
})
.option('urlPrefix', {
type: 'string',
describe: 'URL prefix to add to the beginning of all filenames',
default: DEFAULT_URL_PREFIX,
})
.option('buildPath', {
type: 'string',
describe: 'The path to the build directory',
default: DEFAULT_BUILD_PATH,
})
.option('disableDebugIds', {
type: 'boolean',
describe: 'Disable the injection and upload of debug ids',
default: false,
})
.option('deleteAfterUpload', {
type: 'boolean',
describe: 'Delete sourcemaps after uploading',
default: true,
})
.usage(
'Usage: $0\n' +
' [--release RELEASE]\n' +
' [--org ORG]\n' +
' [--project PROJECT]\n' +
' [--url URL]\n' +
' [--urlPrefix URL_PREFIX]\n' +
' [--buildPath BUILD_PATH]\n\n' +
' [--disableDebugIds true|false]\n\n' +
' [--deleteAfterUpload true|false]\n\n' +
'This CLI tool will upload sourcemaps to Sentry for the given release.\n' +
'It has defaults for URL prefix and build path for Remix builds, but you can override them.\n\n' +
'If you need a more advanced configuration, you can use `sentry-cli` instead.\n' +
'https://github.com/getsentry/sentry-cli',
)
.wrap(120).argv;
const USAGE = `Usage: sentry-upload-sourcemaps [options]

Options:
--release RELEASE The release number. If not provided, a new release
id will be determined by Sentry CLI's propose-version.
See: https://docs.sentry.io/product/releases/suspect-commits/#using-the-cli
--org ORG The Sentry organization slug
--project PROJECT The Sentry project slug
--url URL The Sentry server URL
--urlPrefix URL_PREFIX URL prefix to add to the beginning of all filenames
[default: "${DEFAULT_URL_PREFIX}"]
--buildPath BUILD_PATH The path to the build directory
[default: "${DEFAULT_BUILD_PATH}"]
--disableDebugIds Disable the injection and upload of debug ids
[default: false]
--deleteAfterUpload Delete sourcemaps after uploading
[default: true]
--keepAfterUpload Keep sourcemaps after uploading (prevents deletion).
Use this instead of --no-deleteAfterUpload for
compatibility with Node < 20.16.
[default: false]
-h, --help Show this help message

This CLI tool will upload sourcemaps to Sentry for the given release.
It has defaults for URL prefix and build path for Remix builds, but you
can override them.

If you need a more advanced configuration, you can use sentry-cli instead.
https://github.com/getsentry/sentry-cli`;

// Note: Unlike yargs, util.parseArgs with strict mode (the default):
// - Rejects unknown flags (stricter, catches typos)
// - Does not auto-convert kebab-case to camelCase (use --urlPrefix, not --url-prefix)
// - Boolean flags cannot take =true/=false values (use bare --flag to enable)
const { values: argv } = parseArgs({
args: process.argv.slice(2),
options: {
release: { type: 'string' },
org: { type: 'string' },
project: { type: 'string' },
url: { type: 'string' },
urlPrefix: { type: 'string', default: DEFAULT_URL_PREFIX },
buildPath: { type: 'string', default: DEFAULT_BUILD_PATH },
disableDebugIds: { type: 'boolean', default: false },
deleteAfterUpload: { type: 'boolean', default: true },
keepAfterUpload: { type: 'boolean', default: false },
help: { type: 'boolean', short: 'h', default: false },
},
});

if (argv.help) {
// eslint-disable-next-line no-console
console.log(USAGE);
process.exit(0);
}

// --keepAfterUpload overrides --deleteAfterUpload to prevent source map deletion.
// This flag exists because util.parseArgs does not support --no-deleteAfterUpload
// on Node < 20.16, so without it there is no way to disable deletion.
if (argv.keepAfterUpload) {
argv.deleteAfterUpload = false;
}

const buildPath = argv.buildPath || DEFAULT_BUILD_PATH;
const urlPrefix = argv.urlPrefix || DEFAULT_URL_PREFIX;
Expand Down