@sentry/cli
Advanced tools
Comparing version 1.76.0 to 1.77.0
@@ -1,9 +0,9 @@ | ||
sentry-cli-Darwin-arm64=3ad86772148a987740c0edec2525bb6bb0127eb579a99e64adcef9be317c2acb | ||
sentry-cli-Darwin-universal=1fb8038738889e8afc6b9b24dc388ced67b98bb3153566e347a04965f5f4074a | ||
sentry-cli-Darwin-x86_64=21c2046608eb1d8d17f2c9d597fb06558633ff75ee16602132565176c6e29496 | ||
sentry-cli-Linux-aarch64=bca2a0d97a0deb7f5cb98d47e1b448ffdefe61a1956b41d8cda6730125eced37 | ||
sentry-cli-Linux-armv7=ed818dc2705fcbdb6db24d04b4ecfd42a9cc7b1580f19bd8b5705cb53e5d69cd | ||
sentry-cli-Linux-i686=b085e3e867b25afee4cf780348ebfdbff724da5a785046083fba8c893b274093 | ||
sentry-cli-Linux-x86_64=e19d1e542fe97e711f5d7bb646289f441c4dc08ff92c3937e5289e9fcbfc72e6 | ||
sentry-cli-Windows-i686.exe=7ae0f0cec3098665f9adc1a63e9eba7d945f660de357ea338849895940a784b7 | ||
sentry-cli-Windows-x86_64.exe=6ba5df4f2f2ea5b4b2d5107b3f4c474ea666d9b413b3569bc3353dbcc198677d | ||
sentry-cli-Darwin-arm64=18c1972b79aeaeacb86a512076f355a7a1fd0cf7c0830d41e99ac579f12d6533 | ||
sentry-cli-Darwin-universal=56973c245b5288de36d3fcb3420d67dc7f04e26c2c1cd35379ce617491f1d837 | ||
sentry-cli-Darwin-x86_64=e60f59132433c1ec50e8570766a644a1abcf0e6fdf1f2bcca6de852daa260b62 | ||
sentry-cli-Linux-aarch64=629e731a9dd2e925934eeab5e33f02ba2b60e8c2224b95321ab117a775ed6861 | ||
sentry-cli-Linux-armv7=a8fbf4543d42372743ee8bc0ea7b43cb60b78d3e260d355ad4855c3bacf53f5c | ||
sentry-cli-Linux-i686=9b8982a2ebec0ba0b6199e070362f26e916e79e7d923cf2615f0af85afd1171b | ||
sentry-cli-Linux-x86_64=55fe5bdd1112bd6ff625df8cf97aca3e61df52293ab5b7d8f7466f334298bb27 | ||
sentry-cli-Windows-i686.exe=fd53c35331d6208d9c1a2bdfc156235dcabb841c66162070470946215d4d79dd | ||
sentry-cli-Windows-x86_64.exe=e40cf0bde9c64f9e1f9936350b80e2e14708bca7744ecba0494d489c1ad56eba |
@@ -15,2 +15,6 @@ 'use strict'; | ||
function getBinaryPath() { | ||
if (process.env.SENTRY_BINARY_PATH) { | ||
return process.env.SENTRY_BINARY_PATH; | ||
} | ||
const parts = []; | ||
@@ -65,3 +69,3 @@ parts.push(__dirname); | ||
const paramValue = options[option]; | ||
if (paramValue === undefined) { | ||
if (paramValue === undefined || paramValue === null) { | ||
return newOptions; | ||
@@ -149,3 +153,3 @@ } | ||
*/ | ||
function execute(args, live, silent, configFile, config = {}) { | ||
async function execute(args, live, silent, configFile, config = {}) { | ||
const env = { ...process.env }; | ||
@@ -178,2 +182,8 @@ 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]; | ||
} | ||
@@ -180,0 +190,0 @@ return new Promise((resolve, reject) => { |
@@ -42,7 +42,2 @@ /** | ||
/** | ||
* Unique identifier for the distribution, used to further segment your release. | ||
* Usually your build number. | ||
*/ | ||
dist?: string; | ||
/** | ||
* If true, all logs are suppressed. | ||
@@ -56,2 +51,7 @@ */ | ||
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,3 +64,5 @@ | ||
*/ | ||
export type SourceMapsPathDescriptor = Omit<SentryCliUploadSourceMapsOptions, 'include'> & { paths: string[] } | ||
export type SourceMapsPathDescriptor = Omit<SentryCliUploadSourceMapsOptions, 'include'> & { | ||
paths: string[]; | ||
}; | ||
@@ -92,2 +94,11 @@ 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. | ||
@@ -123,2 +134,11 @@ * 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; | ||
} | ||
@@ -184,27 +204,15 @@ | ||
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>; | ||
@@ -223,12 +231,12 @@ 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; | ||
public execute(args: string[], live: boolean): Promise<string>; | ||
} | ||
} |
@@ -53,3 +53,3 @@ 'use strict'; | ||
*/ | ||
new(release, options) { | ||
async new(release, options) { | ||
const args = ['releases', 'new', release].concat(helper.getProjectFlagsFromOptions(options)); | ||
@@ -80,3 +80,3 @@ return this.execute(args, null); | ||
*/ | ||
setCommits(release, options) { | ||
async setCommits(release, options) { | ||
if (!options || (!options.auto && (!options.repo || !options.commit))) { | ||
@@ -100,6 +100,2 @@ 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)); | ||
@@ -116,3 +112,3 @@ } | ||
*/ | ||
finalize(release) { | ||
async finalize(release) { | ||
return this.execute(['releases', 'finalize', release], null); | ||
@@ -128,6 +124,5 @@ } | ||
*/ | ||
proposeVersion() { | ||
return this.execute(['releases', 'propose-version'], null).then( | ||
version => version && version.trim() | ||
); | ||
async proposeVersion() { | ||
const version = await this.execute(['releases', 'propose-version'], null); | ||
return version.trim(); | ||
} | ||
@@ -153,2 +148,3 @@ | ||
* sourceMapReference: true, // add a source map reference to source files | ||
* dedupe: true, // deduplicate already uploaded files | ||
* stripPrefix: [], // remove certain prefices from filenames | ||
@@ -160,3 +156,4 @@ * 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 | ||
* projects: ['node'], // provide a list of projects | ||
* decompress: false // decompress gzip files before uploading | ||
* }); | ||
@@ -169,3 +166,3 @@ * | ||
*/ | ||
uploadSourceMaps(release, options) { | ||
async uploadSourceMaps(release, options) { | ||
if (!options || !options.include || !Array.isArray(options.include)) { | ||
@@ -180,3 +177,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; | ||
@@ -212,3 +209,3 @@ let uploadPaths; | ||
return uploadPaths.map(path => | ||
return uploadPaths.map((path) => | ||
// `execute()` is async and thus we're returning a promise here | ||
@@ -234,3 +231,3 @@ this.execute(helper.prepareCommand([...args, path], SOURCEMAPS_SCHEMA, newOptions), true) | ||
*/ | ||
listDeploys(release) { | ||
async listDeploys(release) { | ||
return this.execute(['releases', 'deploys', release, 'list'], null); | ||
@@ -261,3 +258,3 @@ } | ||
*/ | ||
newDeploy(release, options) { | ||
async newDeploy(release, options) { | ||
if (!options || !options.env) { | ||
@@ -276,3 +273,3 @@ throw new Error('options.env must be a vaild name'); | ||
*/ | ||
execute(args, live) { | ||
async execute(args, live) { | ||
return helper.execute(args, live, this.options.silent, this.configFile, this.options); | ||
@@ -279,0 +276,0 @@ } |
@@ -14,2 +14,6 @@ module.exports = { | ||
}, | ||
decompress: { | ||
param: '--decompress', | ||
type: 'boolean', | ||
}, | ||
rewrite: { | ||
@@ -24,2 +28,6 @@ param: '--rewrite', | ||
}, | ||
dedupe: { | ||
invertedParam: '--no-dedupe', | ||
type: 'boolean', | ||
}, | ||
stripPrefix: { | ||
@@ -49,2 +57,6 @@ param: '--strip-prefix', | ||
}, | ||
useArtifactBundle: { | ||
param: '--use-artifact-bundle', | ||
type: 'boolean', | ||
}, | ||
}; |
{ | ||
"name": "@sentry/cli", | ||
"version": "1.76.0", | ||
"version": "1.77.0", | ||
"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": ">= 8" | ||
"node": ">= 10" | ||
}, | ||
"main": "js/index.js", | ||
"types": "js/index.d.ts", | ||
"bin": { | ||
"sentry-cli": "bin/sentry-cli" | ||
}, | ||
"dependencies": { | ||
"https-proxy-agent": "^5.0.0", | ||
"node-fetch": "^2.6.7", | ||
"progress": "^2.0.3", | ||
"proxy-from-env": "^1.1.0", | ||
"which": "^2.0.2" | ||
}, | ||
"devDependencies": { | ||
"@vercel/nft": "^0.22.1", | ||
"eslint": "^7.32.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"jest": "^27.5.1", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^2.6.2" | ||
}, | ||
"scripts": { | ||
@@ -38,25 +44,7 @@ "install": "node ./scripts/install.js", | ||
}, | ||
"dependencies": { | ||
"https-proxy-agent": "^5.0.0", | ||
"mkdirp": "^0.5.5", | ||
"node-fetch": "^2.6.7", | ||
"progress": "^2.0.3", | ||
"proxy-from-env": "^1.1.0", | ||
"which": "^2.0.2" | ||
}, | ||
"devDependencies": { | ||
"@vercel/nft": "^0.22.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": "^1.19.1" | ||
}, | ||
"jest": { | ||
"collectCoverage": false, | ||
"collectCoverage": true, | ||
"testEnvironment": "node", | ||
"testPathIgnorePatterns": [ | ||
"src/utils" | ||
"<rootDir>/src" | ||
] | ||
@@ -67,6 +55,3 @@ }, | ||
"yarn": "1.22.19" | ||
}, | ||
"publishConfig": { | ||
"tag": "v1" | ||
} | ||
} |
<p align="center"> | ||
<img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" width="280"> | ||
<br /> | ||
<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> | ||
</p> | ||
@@ -15,3 +20,3 @@ | ||
primarily used to upload debug symbols to Sentry if you are not using the | ||
fastlane tools. | ||
Fastlane tools. | ||
@@ -24,9 +29,30 @@ * Downloads can be found under | ||
The recommended way to install is with everybody's favorite curl to bash: | ||
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: | ||
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: | ||
@@ -56,10 +82,18 @@ npm install @sentry/cli | ||
Another option is to use the environment variable `SENTRYCLI_CDNURL`. | ||
There are a few environment variables that you can provide to control the npm installation: | ||
```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. | ||
@@ -85,2 +119,19 @@ | ||
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 | ||
@@ -87,0 +138,0 @@ |
@@ -14,8 +14,6 @@ #!/usr/bin/env node | ||
const fetch = require('node-fetch'); | ||
const HttpsProxyAgent = require('https-proxy-agent'); | ||
const fetch = require('node-fetch'); | ||
const ProgressBar = require('progress'); | ||
const Proxy = require('proxy-from-env'); | ||
// NOTE: Can be dropped in favor of `fs.mkdirSync(path, { recursive: true })` once we stop supporting Node 8.x | ||
const mkdirp = require('mkdirp'); | ||
const which = require('which'); | ||
@@ -27,2 +25,10 @@ | ||
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) { | ||
@@ -44,18 +50,10 @@ const logStream = process.env.SENTRYCLI_LOG_STREAM || defaultStream; | ||
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 shouldRenderProgressBar() { | ||
const silentFlag = process.argv.some(v => v === '--silent'); | ||
const silentFlag = process.argv.some((v) => v === '--silent'); | ||
const silentConfig = process.env.npm_config_loglevel === 'silent'; | ||
// Leave `SENTRY_NO_PROGRESS_BAR` for backwards compatibility | ||
const silentEnv = process.env.SENTRYCLI_NO_PROGRESS_BAR || process.env.SENTRY_NO_PROGRESS_BAR; | ||
const ciEnv = process.env.CI === 'true'; | ||
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); | ||
return !(silentFlag || silentConfig || silentEnv || ciEnv || notTTY); | ||
} | ||
@@ -119,3 +117,3 @@ | ||
return { | ||
tick: length => { | ||
tick: (length) => { | ||
current += length; | ||
@@ -132,17 +130,17 @@ const next = Math.round((current / total) * 100); | ||
function npmCache() { | ||
const env = process.env; | ||
return ( | ||
env.npm_config_cache || | ||
env.npm_config_cache_folder || | ||
env.npm_config_yarn_offline_mirror || | ||
(env.APPDATA ? path.join(env.APPDATA, 'npm-cache') : path.join(os.homedir(), '.npm')) | ||
); | ||
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); | ||
const digest = crypto.createHash('md5').update(url).digest('hex').slice(0, 6); | ||
@@ -157,5 +155,3 @@ return path.join( | ||
function getTempFile(cached) { | ||
return `${cached}.${process.pid}-${Math.random() | ||
.toString(16) | ||
.slice(2)}.tmp`; | ||
return `${cached}.${process.pid}-${Math.random().toString(16).slice(2)}.tmp`; | ||
} | ||
@@ -187,6 +183,3 @@ | ||
const currentHash = crypto | ||
.createHash('sha256') | ||
.update(fs.readFileSync(tempPath)) | ||
.digest('hex'); | ||
const currentHash = crypto.createHash('sha256').update(fs.readFileSync(tempPath)).digest('hex'); | ||
@@ -203,3 +196,3 @@ if (storedHash !== currentHash) { | ||
function downloadBinary() { | ||
async function downloadBinary() { | ||
const arch = os.arch(); | ||
@@ -211,3 +204,5 @@ const platform = os.platform(); | ||
try { | ||
const binPath = which.sync('sentry-cli'); | ||
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}`); | ||
@@ -226,3 +221,3 @@ fs.copyFileSync(binPath, outputPath); | ||
if (!downloadUrl) { | ||
return Promise.reject(new Error(`Unsupported target ${platform}-${arch}`)); | ||
throw new Error(`Unsupported target ${platform}-${arch}`); | ||
} | ||
@@ -234,3 +229,3 @@ | ||
fs.copyFileSync(cachedPath, outputPath); | ||
return Promise.resolve(); | ||
return; | ||
} | ||
@@ -247,70 +242,81 @@ | ||
return fetch(downloadUrl, { | ||
agent, | ||
compress: false, | ||
headers: { | ||
'accept-encoding': 'gzip, deflate, br', | ||
}, | ||
redirect: 'follow', | ||
}) | ||
.then(response => { | ||
if (!response.ok) { | ||
throw new Error( | ||
`Unable to download sentry-cli binary from ${downloadUrl}.\nServer returned ${response.status}: ${response.statusText}.` | ||
); | ||
} | ||
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); | ||
} | ||
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]; | ||
const total = parseInt(response.headers.get('content-length'), 10); | ||
const progressBar = createProgressBar(name, total); | ||
const tempPath = getTempFile(cachedPath); | ||
mkdirp.sync(path.dirname(tempPath)); | ||
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); | ||
} | ||
return new Promise((resolve, reject) => { | ||
response.body | ||
.on('error', e => reject(e)) | ||
.on('data', chunk => progressBar.tick(chunk.length)) | ||
.pipe(decompressor) | ||
.pipe(fs.createWriteStream(tempPath, { mode: '0755' })) | ||
.on('error', e => reject(e)) | ||
.on('close', () => resolve()); | ||
}).then(() => { | ||
if (process.env.SENTRYCLI_SKIP_CHECKSUM_VALIDATION !== '1') { | ||
validateChecksum(tempPath, name); | ||
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')); | ||
} | ||
fs.copyFileSync(tempPath, cachedPath); | ||
fs.copyFileSync(tempPath, outputPath); | ||
fs.unlinkSync(tempPath); | ||
}); | ||
}) | ||
.catch(error => { | ||
if (error instanceof fetch.FetchError) { | ||
throw new Error( | ||
`Unable to download sentry-cli binary from ${downloadUrl}.\nError code: ${error.code}` | ||
); | ||
} else { | ||
throw error; | ||
} | ||
}); | ||
}); | ||
if (process.env.SENTRYCLI_SKIP_CHECKSUM_VALIDATION !== '1') { | ||
validateChecksum(tempPath, name); | ||
} | ||
fs.copyFileSync(tempPath, cachedPath); | ||
fs.copyFileSync(tempPath, outputPath); | ||
fs.unlinkSync(tempPath); | ||
} | ||
function checkVersion() { | ||
return helper.execute(['--version']).then(output => { | ||
const version = output.replace('sentry-cli ', '').trim(); | ||
const expected = process.env.SENTRYCLI_LOCAL_CDNURL ? 'DEV' : pkgInfo.version; | ||
if (version !== expected) { | ||
throw new Error(`Unexpected sentry-cli version "${version}", expected "${expected}"`); | ||
} | ||
}); | ||
async function checkVersion() { | ||
const output = await helper.execute(['--version']); | ||
const version = output.replace('sentry-cli ', '').trim(); | ||
const expected = process.env.SENTRYCLI_LOCAL_CDNURL ? 'DEV' : pkgInfo.version; | ||
if (version !== expected) { | ||
throw new Error(`Unexpected sentry-cli version "${version}", expected "${expected}"`); | ||
} | ||
} | ||
@@ -338,9 +344,12 @@ | ||
downloadBinary() | ||
.then(() => checkVersion()) | ||
.then(() => process.exit(0)) | ||
.catch(e => { | ||
(async () => { | ||
try { | ||
await downloadBinary(); | ||
await checkVersion(); | ||
process.exit(0); | ||
} catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.error(e.toString()); | ||
process.exit(1); | ||
}); | ||
} | ||
})(); |
@@ -1,9 +0,1 @@ | ||
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'); | ||
@@ -14,4 +6,3 @@ | ||
// Trace the module entrypoint | ||
nodeFileTrace([entryPoint]).then(result => { | ||
// eslint-disable-next-line no-console | ||
nodeFileTrace([entryPoint]).then((result) => { | ||
console.log('@vercel/nft traced dependencies:', Array.from(result.fileList)); | ||
@@ -21,9 +12,7 @@ | ||
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
5
6
1125
152
4
56845
22
- Removedmkdirp@^0.5.5
- Removedminimist@1.2.8(transitive)
- Removedmkdirp@0.5.6(transitive)