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: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ The following changes only apply when using `sentry-cli` via the npm package [`@

- Fixed misleading error message claiming the server doesn't support chunk uploading when the actual error was a non-existent organization ([#2930](https://github.com/getsentry/sentry-cli/pull/2930)).

### Internal changes

- Removed `node-fetch` dependency when using the NPM package ([#2993](https://github.com/getsentry/sentry-cli/pull/2993))

## 2.58.2

Expand Down
51 changes: 39 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
"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",
"undici": "^7.16.0",
"which": "^2.0.2"
},
"devDependencies": {
Expand Down
49 changes: 21 additions & 28 deletions scripts/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ 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 fetch = require('node-fetch');
const HttpsProxyAgent = require('https-proxy-agent');
const { ProxyAgent, fetch } = require('undici');
const ProgressBar = require('progress');
const Proxy = require('proxy-from-env');
const which = require('which');
Expand Down Expand Up @@ -220,7 +218,7 @@ async function downloadBinary() {
}

const proxyUrl = Proxy.getProxyForUrl(downloadUrl);
const agent = proxyUrl ? new HttpsProxyAgent(proxyUrl) : null;
const dispatcher = proxyUrl ? new ProxyAgent(proxyUrl) : undefined;

logger.log(`Downloading from ${downloadUrl}`);

Expand All @@ -231,12 +229,8 @@ async function downloadBinary() {
let response;
try {
response = await fetch(downloadUrl, {
agent,
compress: false,
headers: {
'accept-encoding': 'gzip, deflate, br',
},
redirect: 'follow',
dispatcher,
});
} catch (error) {
let errorMsg = `Unable to download sentry-cli binary from ${downloadUrl}.\nError message: ${error.message}`;
Expand All @@ -254,39 +248,38 @@ async function downloadBinary() {
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);

// Note: content-length might not be available if response was compressed,
// as native fetch decompresses transparently
const contentLength = response.headers.get('content-length');
const totalBytes = contentLength ? parseInt(contentLength, 10) : 0;
const progressBar = createProgressBar(name, totalBytes);
const tempPath = getTempFile(cachedPath);
fs.mkdirSync(path.dirname(tempPath), { recursive: true });

await new Promise((resolve, reject) => {
response.body
// Convert Web ReadableStream to Node.js stream
const nodeStream = stream.Readable.fromWeb(response.body);

nodeStream
.on('error', (e) => reject(e))
.on('data', (chunk) => {
downloadedBytes += chunk.length;
progressBar.tick(chunk.length);

if (!progressBar.complete) {
progressBar.tick(chunk.length);
}
})
.pipe(decompressor)
.pipe(fs.createWriteStream(tempPath, { mode: '0755' }))
.on('error', (e) => reject(e))
.on('close', () => {
if (downloadedBytes >= totalBytes) {
resolve();
} else {
.on('finish', () => {
// Check if we have a total size to validate against
if (totalBytes > 0 && downloadedBytes < totalBytes) {
reject(new Error('connection interrupted'));
} else {
resolve();
}
});
});
Expand Down
Loading