@sentry/cli 1.77.0 → 1.77.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,7 +50,7 @@ class Releases {
50
50
  * @returns {Promise} A promise that resolves when the release has been created.
51
51
  * @memberof SentryReleases
52
52
  */
53
- async new(release, options) {
53
+ new(release, options) {
54
54
  const args = ['releases', 'new', release].concat(helper.getProjectFlagsFromOptions(options));
55
55
  return this.execute(args, null);
56
56
  }
@@ -76,7 +76,7 @@ class Releases {
76
76
  * @returns {Promise} A promise that resolves when the commits have been associated
77
77
  * @memberof SentryReleases
78
78
  */
79
- async setCommits(release, options) {
79
+ setCommits(release, options) {
80
80
  if (!options || (!options.auto && (!options.repo || !options.commit))) {
81
81
  throw new Error('options.auto, or options.repo and options.commit must be specified');
82
82
  }
@@ -95,6 +95,10 @@ class Releases {
95
95
  commitFlags.push('--ignore-missing');
96
96
  }
97
97
 
98
+ if (options.ignoreEmpty) {
99
+ commitFlags.push('--ignore-empty');
100
+ }
101
+
98
102
  return this.execute(['releases', 'set-commits', release].concat(commitFlags));
99
103
  }
100
104
 
@@ -106,7 +110,7 @@ class Releases {
106
110
  * @returns {Promise} A promise that resolves when the release has been finalized.
107
111
  * @memberof SentryReleases
108
112
  */
109
- async finalize(release) {
113
+ finalize(release) {
110
114
  return this.execute(['releases', 'finalize', release], null);
111
115
  }
112
116
 
@@ -117,9 +121,10 @@ class Releases {
117
121
  * @returns {Promise.<string>} A promise that resolves to the version string.
118
122
  * @memberof SentryReleases
119
123
  */
120
- async proposeVersion() {
121
- const version = await this.execute(['releases', 'propose-version'], null);
122
- return version.trim();
124
+ proposeVersion() {
125
+ return this.execute(['releases', 'propose-version'], null).then(
126
+ version => version && version.trim()
127
+ );
123
128
  }
124
129
 
125
130
  /**
@@ -140,15 +145,13 @@ class Releases {
140
145
  * ignoreFile: null, // path to a file with ignore rules
141
146
  * rewrite: false, // preprocess sourcemaps before uploading
142
147
  * sourceMapReference: true, // add a source map reference to source files
143
- * dedupe: true, // deduplicate already uploaded files
144
148
  * stripPrefix: [], // remove certain prefices from filenames
145
149
  * stripCommonPrefix: false, // guess common prefices to remove from filenames
146
150
  * validate: false, // validate source maps and cancel the upload on error
147
151
  * urlPrefix: '', // add a prefix source map urls after stripping them
148
152
  * urlSuffix: '', // add a suffix source map urls after stripping them
149
153
  * ext: ['js', 'map', 'jsbundle', 'bundle'], // override file extensions to scan for
150
- * projects: ['node'], // provide a list of projects
151
- * decompress: false // decompress gzip files before uploading
154
+ * projects: ['node'] // provide a list of projects
152
155
  * });
153
156
  *
154
157
  * @param {string} release Unique name of the release.
@@ -156,7 +159,7 @@ class Releases {
156
159
  * @returns {Promise} A promise that resolves when the upload has completed successfully.
157
160
  * @memberof SentryReleases
158
161
  */
159
- async uploadSourceMaps(release, options) {
162
+ uploadSourceMaps(release, options) {
160
163
  if (!options || !options.include || !Array.isArray(options.include)) {
161
164
  throw new Error(
162
165
  '`options.include` must be a vaild array of paths and/or path descriptor objects.'
@@ -166,7 +169,7 @@ class Releases {
166
169
  // Each entry in the `include` array will map to an array of promises, which
167
170
  // will in turn contain one promise per literal path value. Thus `uploads`
168
171
  // will be an array of Promise arrays, which we'll flatten later.
169
- const uploads = options.include.map((includeEntry) => {
172
+ const uploads = options.include.map(includeEntry => {
170
173
  let pathOptions;
171
174
  let uploadPaths;
172
175
 
@@ -197,7 +200,7 @@ class Releases {
197
200
  .concat(helper.getProjectFlagsFromOptions(options))
198
201
  .concat(['files', release, 'upload-sourcemaps']);
199
202
 
200
- return uploadPaths.map((path) =>
203
+ return uploadPaths.map(path =>
201
204
  // `execute()` is async and thus we're returning a promise here
202
205
  this.execute(helper.prepareCommand([...args, path], SOURCEMAPS_SCHEMA, newOptions), true)
203
206
  );
@@ -218,7 +221,7 @@ class Releases {
218
221
  * @returns {Promise} A promise that resolves when the list comes back from the server.
219
222
  * @memberof SentryReleases
220
223
  */
221
- async listDeploys(release) {
224
+ listDeploys(release) {
222
225
  return this.execute(['releases', 'deploys', release, 'list'], null);
223
226
  }
224
227
 
@@ -244,7 +247,7 @@ class Releases {
244
247
  * @returns {Promise} A promise that resolves when the deploy has been created.
245
248
  * @memberof SentryReleases
246
249
  */
247
- async newDeploy(release, options) {
250
+ newDeploy(release, options) {
248
251
  if (!options || !options.env) {
249
252
  throw new Error('options.env must be a vaild name');
250
253
  }
@@ -258,7 +261,7 @@ class Releases {
258
261
  * @param {boolean} live We inherit stdio to display `sentry-cli` output directly.
259
262
  * @returns {Promise.<string>} A promise that resolves to the standard output.
260
263
  */
261
- async execute(args, live) {
264
+ execute(args, live) {
262
265
  return helper.execute(args, live, this.options.silent, this.configFile, this.options);
263
266
  }
264
267
  }
@@ -11,10 +11,6 @@ module.exports = {
11
11
  param: '--dist',
12
12
  type: 'string',
13
13
  },
14
- decompress: {
15
- param: '--decompress',
16
- type: 'boolean',
17
- },
18
14
  rewrite: {
19
15
  param: '--rewrite',
20
16
  invertedParam: '--no-rewrite',
@@ -24,10 +20,6 @@ module.exports = {
24
20
  invertedParam: '--no-sourcemap-reference',
25
21
  type: 'boolean',
26
22
  },
27
- dedupe: {
28
- invertedParam: '--no-dedupe',
29
- type: 'boolean',
30
- },
31
23
  stripPrefix: {
32
24
  param: '--strip-prefix',
33
25
  type: 'array',
@@ -52,8 +44,4 @@ module.exports = {
52
44
  param: '--ext',
53
45
  type: 'array',
54
46
  },
55
- useArtifactBundle: {
56
- param: '--use-artifact-bundle',
57
- type: 'boolean',
58
- },
59
47
  };
package/package.json CHANGED
@@ -1,34 +1,28 @@
1
1
  {
2
2
  "name": "@sentry/cli",
3
- "version": "1.77.0",
3
+ "version": "1.77.1",
4
4
  "description": "A command line utility to work with Sentry. https://docs.sentry.io/hosted/learn/cli/",
5
- "repository": "git://github.com/getsentry/sentry-cli.git",
6
5
  "homepage": "https://docs.sentry.io/hosted/learn/cli/",
7
- "author": "Sentry",
8
6
  "license": "BSD-3-Clause",
7
+ "keywords": [
8
+ "sentry",
9
+ "sentry-cli",
10
+ "cli"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/getsentry/sentry-cli"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/getsentry/sentry-cli/issues"
18
+ },
9
19
  "engines": {
10
- "node": ">= 10"
20
+ "node": ">= 8"
11
21
  },
12
22
  "main": "js/index.js",
13
- "types": "js/index.d.ts",
14
23
  "bin": {
15
24
  "sentry-cli": "bin/sentry-cli"
16
25
  },
17
- "dependencies": {
18
- "https-proxy-agent": "^5.0.0",
19
- "node-fetch": "^2.6.7",
20
- "progress": "^2.0.3",
21
- "proxy-from-env": "^1.1.0",
22
- "which": "^2.0.2"
23
- },
24
- "devDependencies": {
25
- "@vercel/nft": "^0.22.1",
26
- "eslint": "^7.32.0",
27
- "eslint-config-prettier": "^8.5.0",
28
- "jest": "^27.5.1",
29
- "npm-run-all": "^4.1.5",
30
- "prettier": "^2.6.2"
31
- },
32
26
  "scripts": {
33
27
  "install": "node ./scripts/install.js",
34
28
  "fix": "npm-run-all fix:eslint fix:prettier",
@@ -41,15 +35,36 @@
41
35
  "test:prettier": "prettier --check bin/* scripts/**/*.js js/**/*.js",
42
36
  "test:vercel-nft": "node scripts/test-vercel-nft.js"
43
37
  },
38
+ "dependencies": {
39
+ "https-proxy-agent": "^5.0.0",
40
+ "mkdirp": "^0.5.5",
41
+ "node-fetch": "^2.6.7",
42
+ "progress": "^2.0.3",
43
+ "proxy-from-env": "^1.1.0",
44
+ "which": "^2.0.2"
45
+ },
46
+ "devDependencies": {
47
+ "@vercel/nft": "^0.22.1",
48
+ "eslint": "^6.8.0",
49
+ "eslint-config-airbnb-base": "^14.1.0",
50
+ "eslint-config-prettier": "^6.10.1",
51
+ "eslint-plugin-import": "^2.20.2",
52
+ "jest": "^25.3.0",
53
+ "npm-run-all": "^4.1.5",
54
+ "prettier": "^1.19.1"
55
+ },
44
56
  "jest": {
45
- "collectCoverage": true,
57
+ "collectCoverage": false,
46
58
  "testEnvironment": "node",
47
59
  "testPathIgnorePatterns": [
48
- "<rootDir>/src"
60
+ "src/utils"
49
61
  ]
50
62
  },
51
63
  "volta": {
52
64
  "node": "10.24.1",
53
65
  "yarn": "1.22.19"
66
+ },
67
+ "publishConfig": {
68
+ "tag": "v1"
54
69
  }
55
70
  }
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
2
  set -eux
3
3
 
4
- DOCKER_IMAGE="messense/rust-musl-cross:${DOCKER_TAG}"
4
+ DOCKER_IMAGE="getsentry/rust-musl-cross:${DOCKER_TAG}"
5
5
  BUILD_DIR="/work"
6
6
 
7
7
  DOCKER_RUN_OPTS="
@@ -9,6 +9,7 @@ DOCKER_RUN_OPTS="
9
9
  -v $(pwd):${BUILD_DIR}:ro
10
10
  -v $(pwd)/target:${BUILD_DIR}/target
11
11
  -v $HOME/.cargo/registry:/root/.cargo/registry
12
+ -e ARMV7_UNKNOWN_LINUX_MUSLEABI_OPENSSL_NO_VENDOR=1
12
13
  ${DOCKER_IMAGE}
13
14
  "
14
15
 
@@ -2,312 +2,10 @@
2
2
 
3
3
  'use strict';
4
4
 
5
- const fs = require('fs');
6
5
  const http = require('http');
7
- const os = require('os');
6
+ const fs = require('fs');
8
7
  const path = require('path');
9
- const crypto = require('crypto');
10
- const zlib = require('zlib');
11
- const stream = require('stream');
12
- const process = require('process');
13
-
14
- const fetch = require('node-fetch');
15
- const HttpsProxyAgent = require('https-proxy-agent');
16
- const ProgressBar = require('progress');
17
- const Proxy = require('proxy-from-env');
18
- const which = require('which');
19
-
20
- const helper = require('../js/helper');
21
- const pkgInfo = require('../package.json');
22
- const Logger = require('../js/logger');
23
-
24
- const logger = new Logger(getLogStream('stderr'));
25
-
26
- const CDN_URL =
27
- process.env.SENTRYCLI_LOCAL_CDNURL ||
28
- process.env.npm_config_sentrycli_cdnurl ||
29
- process.env.SENTRYCLI_CDNURL ||
30
- 'https://downloads.sentry-cdn.com/sentry-cli';
31
-
32
- function getLogStream(defaultStream) {
33
- const logStream = process.env.SENTRYCLI_LOG_STREAM || defaultStream;
34
-
35
- if (logStream === 'stdout') {
36
- return process.stdout;
37
- }
38
-
39
- if (logStream === 'stderr') {
40
- return process.stderr;
41
- }
42
-
43
- throw new Error(
44
- `Incorrect SENTRYCLI_LOG_STREAM env variable. Possible values: 'stdout' | 'stderr'`
45
- );
46
- }
47
-
48
- function shouldRenderProgressBar() {
49
- const silentFlag = process.argv.some((v) => v === '--silent');
50
- const silentConfig = process.env.npm_config_loglevel === 'silent';
51
- const silentEnv = process.env.SENTRYCLI_NO_PROGRESS_BAR;
52
- const ciEnv = process.env.CI === 'true' || process.env.CI === '1';
53
- const notTTY = !process.stdout.isTTY;
54
- // If any of possible options is set, skip rendering of progress bar
55
- return !(silentFlag || silentConfig || silentEnv || ciEnv || notTTY);
56
- }
57
-
58
- function getDownloadUrl(platform, arch) {
59
- const releasesUrl = `${CDN_URL}/${pkgInfo.version}/sentry-cli`;
60
- let archString = '';
61
- switch (arch) {
62
- case 'x64':
63
- archString = 'x86_64';
64
- break;
65
- case 'x86':
66
- case 'ia32':
67
- archString = 'i686';
68
- break;
69
- case 'arm64':
70
- archString = 'aarch64';
71
- break;
72
- case 'arm':
73
- archString = 'armv7';
74
- break;
75
- default:
76
- archString = arch;
77
- }
78
- switch (platform) {
79
- case 'darwin':
80
- return `${releasesUrl}-Darwin-universal`;
81
- case 'win32':
82
- return `${releasesUrl}-Windows-${archString}.exe`;
83
- case 'linux':
84
- case 'freebsd':
85
- return `${releasesUrl}-Linux-${archString}`;
86
- default:
87
- return null;
88
- }
89
- }
90
-
91
- function createProgressBar(name, total) {
92
- const incorrectTotal = typeof total !== 'number' || Number.isNaN(total);
93
-
94
- if (incorrectTotal || !shouldRenderProgressBar()) {
95
- return {
96
- tick: () => {},
97
- };
98
- }
99
-
100
- const logStream = getLogStream('stdout');
101
-
102
- if (logStream.isTTY) {
103
- return new ProgressBar(`fetching ${name} :bar :percent :etas`, {
104
- complete: '█',
105
- incomplete: '░',
106
- width: 20,
107
- total,
108
- });
109
- }
110
-
111
- let pct = null;
112
- let current = 0;
113
- return {
114
- tick: (length) => {
115
- current += length;
116
- const next = Math.round((current / total) * 100);
117
- if (next > pct) {
118
- pct = next;
119
- logStream.write(`fetching ${name} ${pct}%\n`);
120
- }
121
- },
122
- };
123
- }
124
-
125
- function npmCache() {
126
- const keys = ['npm_config_cache', 'npm_config_cache_folder', 'npm_config_yarn_offline_mirror'];
127
-
128
- for (let key of [...keys, ...keys.map((k) => k.toUpperCase())]) {
129
- if (process.env[key]) return process.env[key];
130
- }
131
-
132
- if (process.env.APPDATA) {
133
- return path.join(process.env.APPDATA, 'npm-cache');
134
- }
135
-
136
- return path.join(os.homedir(), '.npm');
137
- }
138
-
139
- function getCachedPath(url) {
140
- const digest = crypto.createHash('md5').update(url).digest('hex').slice(0, 6);
141
-
142
- return path.join(
143
- npmCache(),
144
- 'sentry-cli',
145
- `${digest}-${path.basename(url).replace(/[^a-zA-Z0-9.]+/g, '-')}`
146
- );
147
- }
148
-
149
- function getTempFile(cached) {
150
- return `${cached}.${process.pid}-${Math.random().toString(16).slice(2)}.tmp`;
151
- }
152
-
153
- function validateChecksum(tempPath, name) {
154
- let storedHash;
155
- try {
156
- const checksums = fs.readFileSync(path.join(__dirname, '../checksums.txt'), 'utf8');
157
- const entries = checksums.split('\n');
158
- for (let i = 0; i < entries.length; i++) {
159
- const [key, value] = entries[i].split('=');
160
- if (key === name) {
161
- storedHash = value;
162
- break;
163
- }
164
- }
165
- } catch (e) {
166
- logger.log(
167
- 'Checksums are generated when the package is published to npm. They are not available directly in the source repository. Skipping validation.'
168
- );
169
- return;
170
- }
171
-
172
- if (!storedHash) {
173
- logger.log(`Checksum for ${name} not found, skipping validation.`);
174
- return;
175
- }
176
-
177
- const currentHash = crypto.createHash('sha256').update(fs.readFileSync(tempPath)).digest('hex');
178
-
179
- if (storedHash !== currentHash) {
180
- fs.unlinkSync(tempPath);
181
- throw new Error(
182
- `Checksum validation for ${name} failed.\nExpected: ${storedHash}\nReceived: ${currentHash}`
183
- );
184
- } else {
185
- logger.log('Checksum validation passed.');
186
- }
187
- }
188
-
189
- async function downloadBinary() {
190
- const arch = os.arch();
191
- const platform = os.platform();
192
- const outputPath = helper.getPath();
193
-
194
- if (process.env.SENTRYCLI_USE_LOCAL === '1') {
195
- try {
196
- const binPaths = which.sync('sentry-cli', { all: true });
197
- if (!binPaths.length) throw new Error('Binary not found');
198
- const binPath = binPaths[binPaths.length - 1];
199
- logger.log(`Using local binary: ${binPath}`);
200
- fs.copyFileSync(binPath, outputPath);
201
- return Promise.resolve();
202
- } catch (e) {
203
- throw new Error(
204
- 'Configured installation of local binary, but it was not found.' +
205
- 'Make sure that `sentry-cli` executable is available in your $PATH or disable SENTRYCLI_USE_LOCAL env variable.'
206
- );
207
- }
208
- }
209
-
210
- const downloadUrl = getDownloadUrl(platform, arch);
211
- if (!downloadUrl) {
212
- throw new Error(`Unsupported target ${platform}-${arch}`);
213
- }
214
-
215
- const cachedPath = getCachedPath(downloadUrl);
216
- if (fs.existsSync(cachedPath)) {
217
- logger.log(`Using cached binary: ${cachedPath}`);
218
- fs.copyFileSync(cachedPath, outputPath);
219
- return;
220
- }
221
-
222
- const proxyUrl = Proxy.getProxyForUrl(downloadUrl);
223
- const agent = proxyUrl ? new HttpsProxyAgent(proxyUrl) : null;
224
-
225
- logger.log(`Downloading from ${downloadUrl}`);
226
-
227
- if (proxyUrl) {
228
- logger.log(`Using proxy URL: ${proxyUrl}`);
229
- }
230
-
231
- let response;
232
- try {
233
- response = await fetch(downloadUrl, {
234
- agent,
235
- compress: false,
236
- headers: {
237
- 'accept-encoding': 'gzip, deflate, br',
238
- },
239
- redirect: 'follow',
240
- });
241
- } catch (error) {
242
- let errorMsg = `Unable to download sentry-cli binary from ${downloadUrl}.\nError message: ${error.message}`;
243
- if (error.code) {
244
- errorMsg += `\nError code: ${error.code}`;
245
- }
246
- throw new Error(errorMsg);
247
- }
248
-
249
- if (!response.ok) {
250
- let errorMsg = `Unable to download sentry-cli binary from ${downloadUrl}.\nServer returned: ${response.status}`;
251
- if (response.statusText) {
252
- errorMsg += ` - ${response.statusText}`;
253
- }
254
- throw new Error(errorMsg);
255
- }
256
-
257
- const contentEncoding = response.headers.get('content-encoding');
258
- let decompressor;
259
- if (/\bgzip\b/.test(contentEncoding)) {
260
- decompressor = zlib.createGunzip();
261
- } else if (/\bdeflate\b/.test(contentEncoding)) {
262
- decompressor = zlib.createInflate();
263
- } else if (/\bbr\b/.test(contentEncoding)) {
264
- decompressor = zlib.createBrotliDecompress();
265
- } else {
266
- decompressor = new stream.PassThrough();
267
- }
268
- const name = downloadUrl.match(/.*\/(.*?)$/)[1];
269
- let downloadedBytes = 0;
270
- const totalBytes = parseInt(response.headers.get('content-length'), 10);
271
- const progressBar = createProgressBar(name, totalBytes);
272
- const tempPath = getTempFile(cachedPath);
273
- fs.mkdirSync(path.dirname(tempPath), { recursive: true });
274
-
275
- await new Promise((resolve, reject) => {
276
- response.body
277
- .on('error', (e) => reject(e))
278
- .on('data', (chunk) => {
279
- downloadedBytes += chunk.length;
280
- progressBar.tick(chunk.length);
281
- })
282
- .pipe(decompressor)
283
- .pipe(fs.createWriteStream(tempPath, { mode: '0755' }))
284
- .on('error', (e) => reject(e))
285
- .on('close', () => {
286
- if (downloadedBytes >= totalBytes) {
287
- resolve();
288
- } else {
289
- reject(new Error('connection interrupted'));
290
- }
291
- });
292
- });
293
-
294
- if (process.env.SENTRYCLI_SKIP_CHECKSUM_VALIDATION !== '1') {
295
- validateChecksum(tempPath, name);
296
- }
297
-
298
- fs.copyFileSync(tempPath, cachedPath);
299
- fs.copyFileSync(tempPath, outputPath);
300
- fs.unlinkSync(tempPath);
301
- }
302
-
303
- async function checkVersion() {
304
- const output = await helper.execute(['--version']);
305
- const version = output.replace('sentry-cli ', '').trim();
306
- const expected = process.env.SENTRYCLI_LOCAL_CDNURL ? 'DEV' : pkgInfo.version;
307
- if (version !== expected) {
308
- throw new Error(`Unexpected sentry-cli version "${version}", expected "${expected}"`);
309
- }
310
- }
8
+ const { downloadBinary } = require('../js/install');
311
9
 
312
10
  if (process.env.SENTRYCLI_LOCAL_CDNURL) {
313
11
  // For testing, mock the CDN by spawning a local server
@@ -324,19 +22,10 @@ if (process.env.SENTRYCLI_LOCAL_CDNURL) {
324
22
  process.on('exit', () => server.close());
325
23
  }
326
24
 
327
- if (process.env.SENTRYCLI_SKIP_DOWNLOAD === '1') {
328
- logger.log(`Skipping download because SENTRYCLI_SKIP_DOWNLOAD=1 detected.`);
329
- process.exit(0);
330
- }
331
-
332
- (async () => {
333
- try {
334
- await downloadBinary();
335
- await checkVersion();
336
- process.exit(0);
337
- } catch (e) {
25
+ downloadBinary()
26
+ .then(() => process.exit(0))
27
+ .catch(e => {
338
28
  // eslint-disable-next-line no-console
339
29
  console.error(e.toString());
340
30
  process.exit(1);
341
- }
342
- })();
31
+ });
@@ -1,16 +1,27 @@
1
+ const major = process.versions.node.split('.')[0];
2
+
3
+ // @vercel/nft doe not support Node.js v8
4
+ if (major < 10) {
5
+ process.exit(0);
6
+ }
7
+
8
+ // eslint-disable-next-line import/no-extraneous-dependencies
1
9
  const { nodeFileTrace } = require('@vercel/nft');
2
10
 
3
11
  const entryPoint = require.resolve('..');
4
12
 
5
13
  // Trace the module entrypoint
6
- nodeFileTrace([entryPoint]).then((result) => {
14
+ nodeFileTrace([entryPoint]).then(result => {
15
+ // eslint-disable-next-line no-console
7
16
  console.log('@vercel/nft traced dependencies:', Array.from(result.fileList));
8
17
 
9
18
  // If either binary is picked up, fail the test
10
19
  if (result.fileList.has('sentry-cli') || result.fileList.has('sentry-cli.exe')) {
20
+ // eslint-disable-next-line no-console
11
21
  console.error('ERROR: The sentry-cli binary should not be found by @vercel/nft');
12
22
  process.exit(-1);
13
23
  } else {
24
+ // eslint-disable-next-line no-console
14
25
  console.log('The sentry-cli binary was not traced by @vercel/nft');
15
26
  }
16
27
  });