Socket
Socket
Sign inDemoInstall

@sentry/cli

Package Overview
Dependencies
17
Maintainers
11
Versions
214
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.77.2 to 1.77.3

CHANGELOG.md

25

checksums.txt

@@ -1,9 +0,16 @@

sentry-cli-Darwin-arm64=a69b907a4984a5d69fdb8fa018d08e45254e57a7038839a39deee09545137c9c
sentry-cli-Darwin-universal=88648343df5e7e6bbf7e95fb8c67681b7949fdc919c00c0acaedf2ac8e258acc
sentry-cli-Darwin-x86_64=26593639d98aa5e853951d1a4303ab578f1964545984b22e7f51feafcbe56152
sentry-cli-Linux-aarch64=62f023ef7741facc7d4faead1717840aa83572991f9bcf42172b0ad82f27a820
sentry-cli-Linux-armv7=23570b65e0c31428914d388b8e5e7ffb499627af810f60965517148cce0ac6fc
sentry-cli-Linux-i686=a8e77f18ddadb5035d1c54b5978d7528b87fda62804a19a272f21761cdd0c889
sentry-cli-Linux-x86_64=088ac6568445c4ebb5b82652190f51c711e13d40d5bd94a62cc37f2f1865412d
sentry-cli-Windows-i686.exe=1d8a960afa3e6ef6f08125974d2ae2e79e8a7b38ae30f7c0b7a32db26f8b8e8b
sentry-cli-Windows-x86_64.exe=6c30d85138bac891ba490a222870067c82c0617226bcd8b32768f11b7a5c9585
sentry-cli-Darwin-arm64=940be414d1c4a49d36ada2893f66feabe358d4d386d42069abd13adec40b89da
sentry-cli-Darwin-universal=6d88b76f393e2e7d28fdd47e38b967b120cffd63c23f9bcf957bd9649249d819
sentry-cli-Darwin-x86_64=ed0a4656c3748c71b409f6c232ae63c119c8d303cade1ae004e9ca1a4750da7a
sentry-cli-Linux-aarch64=f36e03cfcf93eebc73c93ebf9772afc34bca30ca70e808d964d0e44b7a63c425
sentry-cli-Linux-armv7=ab1d464c92713b06f9156014ac0c075d179aa227416e99a2602ecadce7350ab7
sentry-cli-Linux-i686=ba52347c977fb6d2124fd188da5d3b6c54de59dc98036c27a24f1e7666fe6606
sentry-cli-Linux-x86_64=3188668e55aad1fec58d13ca695d2c31131ba90f30ea39885778cfba64429288
sentry-cli-Windows-i686.exe=42142f6477b09c5ea4a65bc93648ae4897196bf478f3aeb561a97ddabc525567
sentry-cli-Windows-x86_64.exe=c6365ff2bd6b067cdd3d24d36ba62c8aefaf1dce7f23b2cdc3c70b8f7e9058d2
sentry-cli-darwin-0.placeholder.tgz=a4bd6f16aa88eba11edf12887810f6e59b264c13f68fc4588a586c1518a7de5d
sentry-cli-linux-arm-0.placeholder.tgz=a4bd6f16aa88eba11edf12887810f6e59b264c13f68fc4588a586c1518a7de5d
sentry-cli-linux-arm64-0.placeholder.tgz=a4bd6f16aa88eba11edf12887810f6e59b264c13f68fc4588a586c1518a7de5d
sentry-cli-linux-i686-0.placeholder.tgz=a4bd6f16aa88eba11edf12887810f6e59b264c13f68fc4588a586c1518a7de5d
sentry-cli-linux-x64-0.placeholder.tgz=a4bd6f16aa88eba11edf12887810f6e59b264c13f68fc4588a586c1518a7de5d
sentry-cli-win32-i686-0.placeholder.tgz=a4bd6f16aa88eba11edf12887810f6e59b264c13f68fc4588a586c1518a7de5d
sentry-cli-win32-x64-0.placeholder.tgz=a4bd6f16aa88eba11edf12887810f6e59b264c13f68fc4588a586c1518a7de5d
'use strict';
const os = require('os');
const path = require('path');
const fs = require('fs');
const childProcess = require('child_process');
const BINARY_DISTRIBUTIONS = [
{ packageName: '@sentry/cli-darwin', subpath: 'bin/sentry-cli' },
{ packageName: '@sentry/cli-linux-x64', subpath: 'bin/sentry-cli' },
{ packageName: '@sentry/cli-linux-i686', subpath: 'bin/sentry-cli' },
{ packageName: '@sentry/cli-linux-arm64', subpath: 'bin/sentry-cli' },
{ packageName: '@sentry/cli-linux-arm', subpath: 'bin/sentry-cli' },
{ packageName: '@sentry/cli-win32-x64', subpath: 'bin/sentry-cli.exe' },
{ packageName: '@sentry/cli-win32-i686', subpath: 'bin/sentry-cli.exe' },
];
/**
* This convoluted function resolves the path to the manually downloaded fallback
* `sentry-cli` binary in a way that can't be analysed by @vercel/nft.
* This convoluted function resolves the path to the `sentry-cli` binary in a
* way that can't be analysed by @vercel/nft.
*
* Without this, the binary can be detected as an asset and included by bundlers
* that use @vercel/nft.
*
* @returns {string} The path to the sentry-cli binary
*/
function getFallbackBinaryPath() {
function getBinaryPath() {
const parts = [];

@@ -35,139 +22,15 @@ parts.push(__dirname);

function getDistributionForThisPlatform() {
const arch = os.arch();
const platform = os.platform();
let packageName = undefined;
if (platform === 'darwin') {
packageName = '@sentry/cli-darwin';
} else if (platform === 'linux' || platform === 'freebsd') {
switch (arch) {
case 'x64':
packageName = '@sentry/cli-linux-x64';
break;
case 'x86':
case 'ia32':
packageName = '@sentry/cli-linux-i686';
break;
case 'arm64':
packageName = '@sentry/cli-linux-arm64';
break;
case 'arm':
packageName = '@sentry/cli-linux-arm';
break;
}
} else if (platform === 'win32') {
switch (arch) {
case 'x64':
packageName = '@sentry/cli-win32-x64';
break;
case 'x86':
case 'ia32':
packageName = '@sentry/cli-win32-i686';
break;
}
}
let subpath = undefined;
switch (platform) {
case 'win32':
subpath = 'bin/sentry-cli.exe';
break;
case 'darwin':
case 'linux':
case 'freebsd':
subpath = 'bin/sentry-cli';
break;
default:
subpath = 'bin/sentry-cli';
break;
}
return { packageName, subpath };
}
/**
* Throws an error with a message stating that Sentry CLI doesn't support the current platform.
*
* @returns {never} nothing. It throws.
* Absolute path to the sentry-cli binary (platform dependent).
* @type {string}
*/
function throwUnsupportedPlatformError() {
throw new Error(
`Unsupported operating system or architecture! Sentry CLI does not work on this architecture.
let binaryPath = getBinaryPath();
Sentry CLI supports:
- Darwin (macOS)
- Linux and FreeBSD on x64, x86, ia32, arm64, and arm architectures
- Windows x64, x86, and ia32 architectures`
);
}
/**
* Tries to find the installed Sentry CLI binary - either by looking into the relevant
* optional dependencies or by trying to resolve the fallback binary.
*
* @returns {string} The path to the sentry-cli binary
*/
function getBinaryPath() {
if (process.env.SENTRY_BINARY_PATH) {
return process.env.SENTRY_BINARY_PATH;
}
const { packageName, subpath } = getDistributionForThisPlatform();
if (packageName === undefined) {
throwUnsupportedPlatformError();
}
let fallbackBinaryPath = getFallbackBinaryPath();
if (fs.existsSync(fallbackBinaryPath)) {
// Since the fallback got installed, the optional dependencies likely didn't get installed, so we just default to the fallback.
return fallbackBinaryPath;
}
let compatibleBinaryPath;
try {
compatibleBinaryPath = require.resolve(`${packageName}/${subpath}`);
} catch (e) {
const otherInstalledDistribution = BINARY_DISTRIBUTIONS.find(({ packageName, subpath }) => {
try {
require.resolve(`${packageName}/${subpath}`);
return true;
} catch (e) {
return false;
}
});
// These error messages are heavily inspired by esbuild's error messages: https://github.com/evanw/esbuild/blob/f3d535262e3998d845d0f102b944ecd5a9efda57/lib/npm/node-platform.ts#L150
if (otherInstalledDistribution) {
throw new Error(`Sentry CLI binary for this platform/architecture not found!
The "${otherInstalledDistribution.packageName}" package is installed, but for the current platform, you should have the "${packageName}" package installed instead. This usually happens if the "@sentry/cli" package is installed on one platform (for example Windows or MacOS) and then the "node_modules" folder is reused on another operating system (for example Linux in Docker).
To fix this, avoid copying the "node_modules" folder, and instead freshly install your dependencies on the target system. You can also configure your package manager to install the right package. For example, yarn has the "supportedArchitectures" feature: https://yarnpkg.com/configuration/yarnrc/#supportedArchitecture.`);
} else {
throw new Error(`Sentry CLI binary for this platform/architecture not found!
It seems like none of the "@sentry/cli" package's optional dependencies got installed. Please make sure your package manager is configured to install optional dependencies. If you are using npm to install your dependencies, please don't set the "--no-optional", "--ignore-optional", or "--omit=optional" flags. Sentry CLI needs the "optionalDependencies" feature in order to install its binary.`);
}
}
return compatibleBinaryPath;
}
/**
* Will be used as the binary path when defined with `mockBinaryPath`.
* @type {string | undefined}
*/
let mockedBinaryPath;
/**
* Overrides the default binary path with a mock value, useful for testing.
*
* @param {string} mockPath The new path to the mock sentry-cli binary
* @deprecated This was used in tests internally and will be removed in the next major version.
*/
// TODO(v3): Remove this function
function mockBinaryPath(mockPath) {
mockedBinaryPath = mockPath;
binaryPath = mockPath;
}

@@ -202,3 +65,3 @@

const paramValue = options[option];
if (paramValue === undefined || paramValue === null) {
if (paramValue === undefined) {
return newOptions;

@@ -259,3 +122,3 @@ }

function getPath() {
return mockedBinaryPath !== undefined ? mockedBinaryPath : getBinaryPath();
return binaryPath;
}

@@ -287,3 +150,3 @@

*/
async function execute(args, live, silent, configFile, config = {}) {
function execute(args, live, silent, configFile, config = {}) {
const env = { ...process.env };

@@ -316,8 +179,2 @@ if (configFile) {

env.CUSTOM_HEADER = config.customHeader;
} else if (config.headers) {
const headers = Object.entries(config.headers).flatMap(([key, value]) => [
'--header',
`${key}:${value}`,
]);
args = [...headers, ...args];
}

@@ -358,5 +215,2 @@ return new Promise((resolve, reject) => {

serializeOptions,
getDistributionForThisPlatform,
throwUnsupportedPlatformError,
getFallbackBinaryPath,
};

@@ -42,2 +42,7 @@ /**

/**
* Unique identifier for the distribution, used to further segment your release.
* Usually your build number.
*/
dist?: string;
/**
* If true, all logs are suppressed.

@@ -51,7 +56,2 @@ */

customHeader?: string;
/**
* Headers added to every outgoing network request.
* This value does not set any env variable, and is overridden by `customHeader`.
*/
headers?: Record<string, string>;
}

@@ -64,5 +64,3 @@

*/
export type SourceMapsPathDescriptor = Omit<SentryCliUploadSourceMapsOptions, 'include'> & {
paths: string[];
};
export type SourceMapsPathDescriptor = Omit<SentryCliUploadSourceMapsOptions, 'include'> & { paths: string[] }

@@ -94,11 +92,2 @@ export interface SentryCliUploadSourceMapsOptions {

/**
* Enables files gzip decompression prior to uploading. Defaults to `false`.
*/
decompress?: boolean;
/**
* Enable artifacts deduplication prior to uploading. This will skip uploading
* any artifacts that are already present on the server. Defaults to `true`.
*/
dedupe?: boolean;
/**
* When paired with the rewrite option this will remove a prefix from uploaded files.

@@ -134,11 +123,2 @@ * For instance you can use this to remove a path that is build machine specific.

ext?: string[];
/**
* Unique identifier for the distribution, used to further segment your release.
* Usually your build number.
*/
dist?: string;
/**
* Use new Artifact Bundles upload, that enables use of Debug ID for Source Maps discovery.
*/
useArtifactBundle?: boolean;
}

@@ -204,15 +184,27 @@

export interface SentryCliReleases {
['new'](release: string, options?: { projects: string[] } | string[]): Promise<string>;
['new'](
release: string,
options?: { projects: string[] } | string[]
): Promise<string>;
setCommits(release: string, options: SentryCliCommitsOptions): Promise<string>;
setCommits(
release: string,
options: SentryCliCommitsOptions
): Promise<string>;
finalize(release: string): Promise<string>;
finalize(release: string): Promise<string>
proposeVersion(): Promise<string>;
proposeVersion(): Promise<string>
uploadSourceMaps(release: string, options: SentryCliUploadSourceMapsOptions): Promise<string>;
uploadSourceMaps(
release: string,
options: SentryCliUploadSourceMapsOptions
): Promise<string>
listDeploys(release: string): Promise<string>;
newDeploy(release: string, options: SentryCliNewDeployOptions): Promise<string>;
newDeploy(
release: string,
options: SentryCliNewDeployOptions
): Promise<string>

@@ -231,12 +223,19 @@ execute(args: string[], live: boolean): Promise<string>;

*/
constructor(configFile?: string | null, options?: SentryCliOptions);
constructor(configFile?: string | null, options?: SentryCliOptions)
public configFile?: string;
public options?: SentryCliOptions;
public releases: SentryCliReleases;
public releases: SentryCliReleases
public static getVersion(): string;
public static getPath(): string;
public execute(args: string[], live: boolean): Promise<string>;
public static getVersion(): string
public static getPath(): string
/**
* Downloads the CLI binary.
* @returns {Promise<void>}
*/
static downloadBinary(logger: { log(...args: unknown[]): void }): Promise<void>;
public execute(args: string[], live: boolean): Promise<string>
}
}

@@ -6,2 +6,3 @@ 'use strict';

const Releases = require('./releases');
const install = require('./install');

@@ -59,2 +60,11 @@ /**

/**
* Downloads the CLI binary.
* @param {any} [configFile] Optional logger to log installation information. Defaults to printing to the terminal.
* @returns {Promise<void>}
*/
static downloadBinary(logger) {
return install.downloadBinary(logger);
}
/**
* See {helper.execute} docs.

@@ -61,0 +71,0 @@ * @param {string[]} args Command line arguments passed to `sentry-cli`.

@@ -53,3 +53,3 @@ 'use strict';

*/
async new(release, options) {
new(release, options) {
const args = ['releases', 'new', release].concat(helper.getProjectFlagsFromOptions(options));

@@ -80,3 +80,3 @@ return this.execute(args, null);

*/
async setCommits(release, options) {
setCommits(release, options) {
if (!options || (!options.auto && (!options.repo || !options.commit))) {

@@ -100,2 +100,6 @@ throw new Error('options.auto, or options.repo and options.commit must be specified');

if (options.ignoreEmpty) {
commitFlags.push('--ignore-empty');
}
return this.execute(['releases', 'set-commits', release].concat(commitFlags));

@@ -112,3 +116,3 @@ }

*/
async finalize(release) {
finalize(release) {
return this.execute(['releases', 'finalize', release], null);

@@ -124,5 +128,6 @@ }

*/
async proposeVersion() {
const version = await this.execute(['releases', 'propose-version'], null);
return version.trim();
proposeVersion() {
return this.execute(['releases', 'propose-version'], null).then(
version => version && version.trim()
);
}

@@ -148,3 +153,2 @@

* sourceMapReference: true, // add a source map reference to source files
* dedupe: true, // deduplicate already uploaded files
* stripPrefix: [], // remove certain prefices from filenames

@@ -156,4 +160,3 @@ * stripCommonPrefix: false, // guess common prefices to remove from filenames

* ext: ['js', 'map', 'jsbundle', 'bundle'], // override file extensions to scan for
* projects: ['node'], // provide a list of projects
* decompress: false // decompress gzip files before uploading
* projects: ['node'] // provide a list of projects
* });

@@ -166,3 +169,3 @@ *

*/
async uploadSourceMaps(release, options) {
uploadSourceMaps(release, options) {
if (!options || !options.include || !Array.isArray(options.include)) {

@@ -177,3 +180,3 @@ throw new Error(

// will be an array of Promise arrays, which we'll flatten later.
const uploads = options.include.map((includeEntry) => {
const uploads = options.include.map(includeEntry => {
let pathOptions;

@@ -209,3 +212,3 @@ let uploadPaths;

return uploadPaths.map((path) =>
return uploadPaths.map(path =>
// `execute()` is async and thus we're returning a promise here

@@ -231,3 +234,3 @@ this.execute(helper.prepareCommand([...args, path], SOURCEMAPS_SCHEMA, newOptions), true)

*/
async listDeploys(release) {
listDeploys(release) {
return this.execute(['releases', 'deploys', release, 'list'], null);

@@ -258,3 +261,3 @@ }

*/
async newDeploy(release, options) {
newDeploy(release, options) {
if (!options || !options.env) {

@@ -273,3 +276,3 @@ throw new Error('options.env must be a vaild name');

*/
async execute(args, live) {
execute(args, live) {
return helper.execute(args, live, this.options.silent, this.configFile, this.options);

@@ -276,0 +279,0 @@ }

@@ -14,6 +14,2 @@ module.exports = {

},
decompress: {
param: '--decompress',
type: 'boolean',
},
rewrite: {

@@ -28,6 +24,2 @@ param: '--rewrite',

},
dedupe: {
invertedParam: '--no-dedupe',
type: 'boolean',
},
stripPrefix: {

@@ -57,6 +49,2 @@ param: '--strip-prefix',

},
useArtifactBundle: {
param: '--use-artifact-bundle',
type: 'boolean',
},
};
{
"name": "@sentry/cli",
"version": "1.77.2",
"version": "1.77.3",
"description": "A command line utility to work with Sentry. https://docs.sentry.io/hosted/learn/cli/",
"repository": "git://github.com/getsentry/sentry-cli.git",
"homepage": "https://docs.sentry.io/hosted/learn/cli/",
"author": "Sentry",
"license": "BSD-3-Clause",
"keywords": [
"sentry",
"sentry-cli",
"cli"
],
"repository": {
"type": "git",
"url": "https://github.com/getsentry/sentry-cli"
},
"bugs": {
"url": "https://github.com/getsentry/sentry-cli/issues"
},
"engines": {
"node": ">= 10"
"node": ">= 8"
},
"main": "js/index.js",
"types": "js/index.d.ts",
"bin": {
"sentry-cli": "bin/sentry-cli"
},
"scripts": {
"install": "node ./scripts/install.js",
"fix": "npm-run-all fix:eslint fix:prettier",
"fix:eslint": "eslint --fix bin/* scripts/**/*.js js/**/*.js",
"fix:prettier": "prettier --write bin/* scripts/**/*.js js/**/*.js",
"test": "npm-run-all test:jest test:eslint test:prettier test:vercel-nft",
"test:jest": "jest",
"test:watch": "jest --watch --notify",
"test:eslint": "eslint bin/* scripts/**/*.js js/**/*.js",
"test:prettier": "prettier --check bin/* scripts/**/*.js js/**/*.js",
"test:vercel-nft": "node scripts/test-vercel-nft.js"
},
"dependencies": {
"https-proxy-agent": "^5.0.0",
"mkdirp": "^0.5.5",
"node-fetch": "^2.6.7",

@@ -26,40 +48,24 @@ "progress": "^2.0.3",

"@vercel/nft": "^0.22.1",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.5.0",
"jest": "^27.5.1",
"eslint": "^6.8.0",
"eslint-config-airbnb-base": "^14.1.0",
"eslint-config-prettier": "^6.10.1",
"eslint-plugin-import": "^2.20.2",
"jest": "^25.3.0",
"npm-run-all": "^4.1.5",
"prettier": "2.8.8"
"prettier": "^1.19.1"
},
"optionalDependencies": {
"@sentry/cli-darwin": "1.77.2",
"@sentry/cli-linux-arm": "1.77.2",
"@sentry/cli-linux-arm64": "1.77.2",
"@sentry/cli-linux-i686": "1.77.2",
"@sentry/cli-linux-x64": "1.77.2",
"@sentry/cli-win32-i686": "1.77.2",
"@sentry/cli-win32-x64": "1.77.2"
},
"scripts": {
"postinstall": "node ./scripts/install.js",
"fix": "npm-run-all fix:eslint fix:prettier",
"fix:eslint": "eslint --fix bin/* scripts/**/*.js js/**/*.js",
"fix:prettier": "prettier --write bin/* scripts/**/*.js js/**/*.js",
"test": "npm-run-all test:jest test:eslint test:prettier test:vercel-nft",
"test:jest": "jest",
"test:watch": "jest --watch --notify",
"test:eslint": "eslint bin/* scripts/**/*.js js/**/*.js",
"test:prettier": "prettier --check bin/* scripts/**/*.js js/**/*.js",
"test:vercel-nft": "node scripts/test-vercel-nft.js"
},
"jest": {
"collectCoverage": true,
"collectCoverage": false,
"testEnvironment": "node",
"testPathIgnorePatterns": [
"<rootDir>/src"
"src/utils"
]
},
"volta": {
"node": "20.10.0",
"node": "10.24.1",
"yarn": "1.22.19"
},
"publishConfig": {
"tag": "v1"
}
}
<p align="center">
<a href="https://sentry.io/?utm_source=github&utm_medium=logo" target="_blank">
<picture>
<source srcset="https://sentry-brand.storage.googleapis.com/sentry-logo-white.png" media="(prefers-color-scheme: dark)" />
<source srcset="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" />
<img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" alt="Sentry" width="280">
</picture>
</a>
<img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" width="280">
<br />
</p>

@@ -20,3 +15,3 @@

primarily used to upload debug symbols to Sentry if you are not using the
Fastlane tools.
fastlane tools.

@@ -29,30 +24,9 @@ * Downloads can be found under

If you are on OS X or Linux, you can use the automated downloader which will fetch the latest release version for you and install it:
The recommended way to install is with everybody's favorite curl to bash:
curl -sL https://sentry.io/get-cli/ | bash
We do, however, encourage you to pin the specific version of the CLI, so your builds are always reproducible.
To do that, you can use the exact same method, with an additional version specifier:
curl -sL https://sentry.io/get-cli/ | SENTRY_CLI_VERSION=2.0.4 bash
This will automatically download the correct version of `sentry-cli` for your operating system and install it. If necessary, it will prompt for your admin password for `sudo`. For a different installation location or for systems without `sudo` (like Windows), you can `export INSTALL_DIR=/custom/installation/path` before running this command.
If you are using `sentry-cli` on Windows environments, [Microsoft Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) is required.
To verify it’s installed correctly you can bring up the help:
sentry-cli --help
### pip
_New in 2.14.3_: `sentry-cli` can also be installed using `pip`:
```bash
pip install sentry-cli
```
### Node
Additionally, you can also install this binary via npm:
Additionally you can also install this binary via npm:

@@ -82,18 +56,10 @@ npm install @sentry/cli

There are a few environment variables that you can provide to control the npm installation:
Another option is to use the environment variable `SENTRYCLI_CDNURL`.
```sh
SENTRYCLI_CDNURL=https://mymirror.local/path npm install @sentry/cli
```
SENTRYCLI_CDNURL=<url> # Use alternative cdn url for downloading binary
SENTRYCLI_USE_LOCAL=1 # Use local instance of sentry-cli binary (looked up via $PATH environment)
SENTRYCLI_SKIP_DOWNLOAD=1 # Skip downloading binary entirely
SENTRYCLI_NO_PROGRESS_BAR=1 # Do not print the progress bar when downloading binary (default for non-TTY environments like CI)
SENTRYCLI_LOG_STREAM=<stdout|stderr> # Changes where to redirect install script output
```
When using `sentry-cli` via JavaScript API or any 3rd party plugin that is consuming said API,
you can also use `SENTRY_BINARY_PATH=<path>` alongside `SENTRYCLI_SKIP_DOWNLOAD=1` to completely
control what binaries are downloaded and used throughout the whole process.
If you're installing the CLI with NPM from behind a proxy, the install script will
use either NPM's configured HTTPS proxy server or the value from your `HTTPS_PROXY`
use either NPM's configured HTTPS proxy server, or the value from your `HTTPS_PROXY`
environment variable.

@@ -119,19 +85,2 @@

Starting version _`2.8.0`_, in case you see `"error: config value 'safe.directory' was not found;"` message,
you also need to correctly set UID and GID of mounted volumes like so:
```sh
docker run --rm -u "$(id -u):$(id -g)" -v $(pwd):/work getsentry/sentry-cli --help
```
This is required due to security issue in older `git` implementations. See [here](https://github.blog/2022-04-12-git-security-vulnerability-announced/) for more details.
## Update
To update sentry-cli to the latest version run:
```sh
sentry-cli update
```
## Compiling

@@ -138,0 +87,0 @@

@@ -5,346 +5,28 @@ #!/usr/bin/env node

const http = require('http');
const fs = require('fs');
const os = require('os');
const path = require('path');
const crypto = require('crypto');
const zlib = require('zlib');
const stream = require('stream');
const process = require('process');
const { downloadBinary } = require('../js/install');
const fetch = require('node-fetch');
const HttpsProxyAgent = require('https-proxy-agent');
const ProgressBar = require('progress');
const Proxy = require('proxy-from-env');
const which = require('which');
const helper = require('../js/helper');
const pkgInfo = require('../package.json');
const Logger = require('../js/logger');
const logger = new Logger(getLogStream('stderr'));
const CDN_URL =
process.env.SENTRYCLI_LOCAL_CDNURL ||
process.env.npm_config_sentrycli_cdnurl ||
process.env.SENTRYCLI_CDNURL ||
'https://downloads.sentry-cdn.com/sentry-cli';
function getLogStream(defaultStream) {
const logStream = process.env.SENTRYCLI_LOG_STREAM || defaultStream;
if (logStream === 'stdout') {
return process.stdout;
}
if (logStream === 'stderr') {
return process.stderr;
}
throw new Error(
`Incorrect SENTRYCLI_LOG_STREAM env variable. Possible values: 'stdout' | 'stderr'`
);
}
function shouldRenderProgressBar() {
const silentFlag = process.argv.some((v) => v === '--silent');
const silentConfig = process.env.npm_config_loglevel === 'silent';
const silentEnv = process.env.SENTRYCLI_NO_PROGRESS_BAR;
const ciEnv = process.env.CI === 'true' || process.env.CI === '1';
const notTTY = !process.stdout.isTTY;
// If any of possible options is set, skip rendering of progress bar
return !(silentFlag || silentConfig || silentEnv || ciEnv || notTTY);
}
function getDownloadUrl(platform, arch) {
const releasesUrl = `${CDN_URL}/${pkgInfo.version}/sentry-cli`;
let archString = '';
switch (arch) {
case 'x64':
archString = 'x86_64';
break;
case 'x86':
case 'ia32':
archString = 'i686';
break;
case 'arm64':
archString = 'aarch64';
break;
case 'arm':
archString = 'armv7';
break;
default:
archString = arch;
}
switch (platform) {
case 'darwin':
return `${releasesUrl}-Darwin-universal`;
case 'win32':
// Windows arm machines can run x64 binaries
if (arch === 'arm64') {
archString = 'x86_64';
}
return `${releasesUrl}-Windows-${archString}.exe`;
case 'linux':
case 'freebsd':
return `${releasesUrl}-Linux-${archString}`;
default:
return null;
}
}
function createProgressBar(name, total) {
const incorrectTotal = typeof total !== 'number' || Number.isNaN(total);
if (incorrectTotal || !shouldRenderProgressBar()) {
return {
tick: () => {},
};
}
const logStream = getLogStream('stdout');
if (logStream.isTTY) {
return new ProgressBar(`fetching ${name} :bar :percent :etas`, {
complete: '█',
incomplete: '░',
width: 20,
total,
if (process.env.SENTRYCLI_LOCAL_CDNURL) {
// For testing, mock the CDN by spawning a local server
const server = http.createServer((request, response) => {
const contents = fs.readFileSync(path.join(__dirname, '../js/__mocks__/sentry-cli'));
response.writeHead(200, {
'Content-Type': 'application/octet-stream',
'Content-Length': String(contents.byteLength),
});
}
response.end(contents);
});
let pct = null;
let current = 0;
return {
tick: (length) => {
current += length;
const next = Math.round((current / total) * 100);
if (next > pct) {
pct = next;
logStream.write(`fetching ${name} ${pct}%\n`);
}
},
};
server.listen(8999);
process.on('exit', () => server.close());
}
function npmCache() {
const keys = ['npm_config_cache', 'npm_config_cache_folder', 'npm_config_yarn_offline_mirror'];
for (let key of [...keys, ...keys.map((k) => k.toUpperCase())]) {
if (process.env[key]) return process.env[key];
}
if (process.env.APPDATA) {
return path.join(process.env.APPDATA, 'npm-cache');
}
return path.join(os.homedir(), '.npm');
}
function getCachedPath(url) {
const digest = crypto.createHash('md5').update(url).digest('hex').slice(0, 6);
return path.join(
npmCache(),
'sentry-cli',
`${digest}-${path.basename(url).replace(/[^a-zA-Z0-9.]+/g, '-')}`
);
}
function getTempFile(cached) {
return `${cached}.${process.pid}-${Math.random().toString(16).slice(2)}.tmp`;
}
function validateChecksum(tempPath, name) {
let storedHash;
try {
const checksums = fs.readFileSync(path.join(__dirname, '../checksums.txt'), 'utf8');
const entries = checksums.split('\n');
for (let i = 0; i < entries.length; i++) {
const [key, value] = entries[i].split('=');
if (key === name) {
storedHash = value;
break;
}
}
} catch (e) {
logger.log(
'Checksums are generated when the package is published to npm. They are not available directly in the source repository. Skipping validation.'
);
return;
}
if (!storedHash) {
logger.log(`Checksum for ${name} not found, skipping validation.`);
return;
}
const currentHash = crypto.createHash('sha256').update(fs.readFileSync(tempPath)).digest('hex');
if (storedHash !== currentHash) {
fs.unlinkSync(tempPath);
throw new Error(
`Checksum validation for ${name} failed.\nExpected: ${storedHash}\nReceived: ${currentHash}`
);
} else {
logger.log('Checksum validation passed.');
}
}
async function downloadBinary() {
const arch = os.arch();
const platform = os.platform();
const outputPath = helper.getFallbackBinaryPath();
if (process.env.SENTRYCLI_USE_LOCAL === '1') {
try {
const binPaths = which.sync('sentry-cli', { all: true });
if (!binPaths.length) throw new Error('Binary not found');
const binPath = binPaths[binPaths.length - 1];
logger.log(`Using local binary: ${binPath}`);
fs.copyFileSync(binPath, outputPath);
return Promise.resolve();
} catch (e) {
throw new Error(
'Configured installation of local binary, but it was not found.' +
'Make sure that `sentry-cli` executable is available in your $PATH or disable SENTRYCLI_USE_LOCAL env variable.'
);
}
}
const downloadUrl = getDownloadUrl(platform, arch);
if (!downloadUrl) {
throw new Error(`Unsupported target ${platform}-${arch}`);
}
const cachedPath = getCachedPath(downloadUrl);
if (fs.existsSync(cachedPath)) {
logger.log(`Using cached binary: ${cachedPath}`);
fs.copyFileSync(cachedPath, outputPath);
return;
}
const proxyUrl = Proxy.getProxyForUrl(downloadUrl);
const agent = proxyUrl ? new HttpsProxyAgent(proxyUrl) : null;
logger.log(`Downloading from ${downloadUrl}`);
if (proxyUrl) {
logger.log(`Using proxy URL: ${proxyUrl}`);
}
let response;
try {
response = await fetch(downloadUrl, {
agent,
compress: false,
headers: {
'accept-encoding': 'gzip, deflate, br',
},
redirect: 'follow',
});
} catch (error) {
let errorMsg = `Unable to download sentry-cli binary from ${downloadUrl}.\nError message: ${error.message}`;
if (error.code) {
errorMsg += `\nError code: ${error.code}`;
}
throw new Error(errorMsg);
}
if (!response.ok) {
let errorMsg = `Unable to download sentry-cli binary from ${downloadUrl}.\nServer returned: ${response.status}`;
if (response.statusText) {
errorMsg += ` - ${response.statusText}`;
}
throw new Error(errorMsg);
}
const contentEncoding = response.headers.get('content-encoding');
let decompressor;
if (/\bgzip\b/.test(contentEncoding)) {
decompressor = zlib.createGunzip();
} else if (/\bdeflate\b/.test(contentEncoding)) {
decompressor = zlib.createInflate();
} else if (/\bbr\b/.test(contentEncoding)) {
decompressor = zlib.createBrotliDecompress();
} else {
decompressor = new stream.PassThrough();
}
const name = downloadUrl.match(/.*\/(.*?)$/)[1];
let downloadedBytes = 0;
const totalBytes = parseInt(response.headers.get('content-length'), 10);
const progressBar = createProgressBar(name, totalBytes);
const tempPath = getTempFile(cachedPath);
fs.mkdirSync(path.dirname(tempPath), { recursive: true });
await new Promise((resolve, reject) => {
response.body
.on('error', (e) => reject(e))
.on('data', (chunk) => {
downloadedBytes += chunk.length;
progressBar.tick(chunk.length);
})
.pipe(decompressor)
.pipe(fs.createWriteStream(tempPath, { mode: '0755' }))
.on('error', (e) => reject(e))
.on('close', () => {
if (downloadedBytes >= totalBytes) {
resolve();
} else {
reject(new Error('connection interrupted'));
}
});
downloadBinary()
.then(() => process.exit(0))
.catch(e => {
// eslint-disable-next-line no-console
console.error(e.toString());
process.exit(1);
});
if (process.env.SENTRYCLI_SKIP_CHECKSUM_VALIDATION !== '1') {
validateChecksum(tempPath, name);
}
fs.copyFileSync(tempPath, cachedPath);
fs.copyFileSync(tempPath, outputPath);
fs.unlinkSync(tempPath);
}
async function checkVersion() {
const output = await helper.execute(['--version']);
const version = output.replace('sentry-cli ', '').trim();
const expected = pkgInfo.version;
if (version !== expected) {
throw new Error(`Unexpected sentry-cli version "${version}", expected "${expected}"`);
}
}
if (process.env.SENTRYCLI_SKIP_DOWNLOAD === '1') {
logger.log(`Skipping download because SENTRYCLI_SKIP_DOWNLOAD=1 detected.`);
process.exit(0);
}
const { packageName: distributionPackageName, subpath: distributionSubpath } =
helper.getDistributionForThisPlatform();
if (distributionPackageName === undefined) {
helper.throwUnsupportedPlatformError();
}
try {
require.resolve(`${distributionPackageName}/${distributionSubpath}`);
// If the `resolve` call succeeds it means a binary was installed successfully via optional dependencies so we can skip the manual postinstall download.
process.exit(0);
} catch (e) {
// Optional dependencies likely didn't get installed - proceed with fallback downloading manually
// Log message inspired by esbuild: https://github.com/evanw/esbuild/blob/914f6080c77cfe32a54888caa51ca6ea13873ce9/lib/npm/node-install.ts#L253
logger.log(
`Sentry CLI failed to locate the "${distributionPackageName}" package after installation!
This can happen if you use an option to disable optional dependencies during installation, like "--no-optional", "--ignore-optional", or "--omit=optional". Sentry CLI uses the "optionalDependencies" package.json feature to install the correct binary for your platform and operating system. This post-install script will now try to work around this by manually downloading the Sentry CLI binary from the Sentry CDN. If this fails, you need to remove the "--no-optional", "--ignore-optional", and "--omit=optional" flags for Sentry CLI to work.`
);
downloadBinary()
.then(() => checkVersion())
.then(() => {
process.exit(0);
})
.catch((e) => {
console.error(e);
process.exit(1);
});
}

@@ -0,1 +1,9 @@

const major = process.versions.node.split('.')[0];
// @vercel/nft doe not support Node.js v8
if (major < 10) {
process.exit(0);
}
// eslint-disable-next-line import/no-extraneous-dependencies
const { nodeFileTrace } = require('@vercel/nft');

@@ -6,3 +14,4 @@

// Trace the module entrypoint
nodeFileTrace([entryPoint]).then((result) => {
nodeFileTrace([entryPoint]).then(result => {
// eslint-disable-next-line no-console
console.log('@vercel/nft traced dependencies:', Array.from(result.fileList));

@@ -12,7 +21,9 @@

if (result.fileList.has('sentry-cli') || result.fileList.has('sentry-cli.exe')) {
// eslint-disable-next-line no-console
console.error('ERROR: The sentry-cli binary should not be found by @vercel/nft');
process.exit(-1);
} else {
// eslint-disable-next-line no-console
console.log('The sentry-cli binary was not traced by @vercel/nft');
}
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc