mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
Reworked analytics
This commit is contained in:
parent
b76f748e73
commit
889c9dbbd4
@ -6,7 +6,7 @@ import {SEGMENT_WRITE_KEY} from './constants';
|
||||
let analytics = null;
|
||||
let userId = null;
|
||||
|
||||
export async function initAnalytics () {
|
||||
export async function initLegacyAnalytics () {
|
||||
analytics = new Analytics(SEGMENT_WRITE_KEY);
|
||||
|
||||
if (!userId) {
|
||||
@ -14,7 +14,7 @@ export async function initAnalytics () {
|
||||
userId = stats._id;
|
||||
|
||||
// Recurse now that we have a userId
|
||||
return await initAnalytics();
|
||||
return await initLegacyAnalytics();
|
||||
}
|
||||
|
||||
analytics.identify({
|
||||
@ -31,7 +31,7 @@ export async function initAnalytics () {
|
||||
console.log(`-- Analytics Initialized for ${userId} --`);
|
||||
}
|
||||
|
||||
export function trackEvent (event, properties = {}) {
|
||||
export function trackLegacyEvent (event, properties = {}) {
|
||||
// Don't track events if we haven't set them up yet
|
||||
if (analytics) {
|
||||
// Add base properties
|
||||
|
@ -6,6 +6,8 @@ export const LOCALSTORAGE_KEY = 'insomnia.state';
|
||||
export const DB_PERSIST_INTERVAL = 1000 * 60 * 10;
|
||||
export const DEBOUNCE_MILLIS = 100;
|
||||
export const REQUEST_TIME_TO_SHOW_COUNTER = 1; // Seconds
|
||||
export const GA_ID = 'UA-9837747-12';
|
||||
export const GA_HOST = 'desktop.insomnia.rest';
|
||||
export const CHANGELOG_URL = 'https://changelog.insomnia.rest/changelog.json';
|
||||
export const STATUS_CODE_PEBKAC = -333;
|
||||
export const LARGE_RESPONSE_MB = 10;
|
||||
|
@ -28,12 +28,11 @@ function lookup (url, forceIPv4) {
|
||||
}
|
||||
|
||||
const v6 = results.find(r => r.family === 6);
|
||||
const v4 = results.find(r => r.family === 4);
|
||||
|
||||
if (v6) {
|
||||
resolve(v6.address);
|
||||
} else {
|
||||
resolve(v4.address);
|
||||
// If no v6, return the first result
|
||||
resolve(results[0].address);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
55
app/backend/ganalytics.js
Normal file
55
app/backend/ganalytics.js
Normal file
@ -0,0 +1,55 @@
|
||||
import * as constants from './constants';
|
||||
import {isDevelopment} from './appInfo';
|
||||
|
||||
let _ga = null;
|
||||
let _sessionId = null;
|
||||
|
||||
export function initAnalytics () {
|
||||
if (isDevelopment()) {
|
||||
console.log('-- Not initializing analytics for dev --');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_sessionId) {
|
||||
_ga = _initGA();
|
||||
}
|
||||
|
||||
if (!localStorage['gaClientId']) {
|
||||
localStorage.setItem('gaClientId', require('node-uuid').v4());
|
||||
}
|
||||
|
||||
const _sessionId = window.localStorage['gaClientId'];
|
||||
|
||||
_ga('create', constants.GA_ID, {'storage': 'none', 'clientId': _sessionId});
|
||||
|
||||
// Disable URL protocol check
|
||||
_ga('set', 'checkProtocolTask', () => null);
|
||||
|
||||
// Set a fake location
|
||||
_ga('set', 'location', `https://${constants.GA_HOST}/`);
|
||||
|
||||
// Track the initial page view
|
||||
_ga('send', 'pageview');
|
||||
|
||||
console.log(`-- Analytics Initialized for ${_sessionId} --`);
|
||||
}
|
||||
|
||||
export function trackEvent (category, action, label) {
|
||||
_ga && _ga('send', 'event', category, action, label);
|
||||
}
|
||||
|
||||
function _initGA () {
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
return window.ga;
|
||||
}
|
@ -1,10 +1,20 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const mkdirp = require('mkdirp');
|
||||
|
||||
class LocalStorage {
|
||||
constructor (path) {
|
||||
this._path = path;
|
||||
this._timeouts = {};
|
||||
|
||||
// No need to wait for this.
|
||||
mkdirp(path, err => {
|
||||
if (err) {
|
||||
console.warn('[localStorage] Failed to create directory', path, err);
|
||||
} else {
|
||||
console.log('[localStorage] initialized');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,8 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Insomnia</title>
|
||||
<script>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
@ -37,9 +39,8 @@
|
||||
// Sentry
|
||||
|
||||
if (process.env.INSOMNIA_ENV !== 'development') {
|
||||
Raven.config('https://fb3242f902b54cdd934b8ffa204426c0:23430fbe203a4189a68efb63c38fc50b@app.getsentry.com/88289', {
|
||||
allowSecretKey: true,
|
||||
logger: 'renderer',
|
||||
Raven.config('https://786e43ae199c4757a9ea4a48a9abd17d@sentry.io/109702', {
|
||||
logger: 'electron.renderer',
|
||||
environment: process.env.INSOMNIA_ENV || 'production',
|
||||
level: 'warning',
|
||||
release: require('./package.json').version,
|
||||
|
12
app/main.js
12
app/main.js
@ -12,11 +12,10 @@ const IS_LINUX = !IS_MAC && !IS_WINDOWS;
|
||||
|
||||
var raven = require('raven');
|
||||
var ravenClient = new raven.Client(
|
||||
'https://fb3242f902b54cdd934b8ffa204426c0:23430fbe203a' +
|
||||
'4189a68efb63c38fc50b@app.getsentry.com/88289', {
|
||||
'https://786e43ae199c4757a9ea4a48a9abd17d@sentry.io/109702', {
|
||||
environment: process.env.INSOMNIA_ENV || 'production',
|
||||
release: require('./package.json').version,
|
||||
logger: 'main'
|
||||
logger: 'electron.main'
|
||||
});
|
||||
|
||||
if (!IS_DEV) {
|
||||
@ -66,13 +65,10 @@ process.on('uncaughtException', e => {
|
||||
});
|
||||
|
||||
autoUpdater.on('error', e => {
|
||||
// Failed to launch auto updater
|
||||
if (IS_DEV) {
|
||||
console.error(e);
|
||||
} else if (e.toString().indexOf('')) {
|
||||
ravenClient.captureError(e, {
|
||||
level: 'warning'
|
||||
});
|
||||
} else {
|
||||
// Don't report autoUpdater error. They are way too noisy
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -11,11 +11,13 @@
|
||||
"dependencies": {
|
||||
"analytics-node": "^2.1.0",
|
||||
"electron-context-menu": "^0.4.0",
|
||||
"electron-cookies": "^1.1.0",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"hkdf": "0.0.2",
|
||||
"httpsnippet": "git@github.com:getinsomnia/httpsnippet.git#a3a2c0a0167fa844bf92df52a1442fa1d68a9053",
|
||||
"json-lint": "^0.1.0",
|
||||
"jsonpath-plus": "^0.15.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nedb": "^1.8.0",
|
||||
"node-forge": "^0.6.43",
|
||||
"node-uuid": "^1.4.7",
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, {Component, PropTypes} from 'react';
|
||||
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';
|
||||
|
||||
import KeyValueEditor from './base/KeyValueEditor';
|
||||
import RequestHeadersEditor from './editors/RequestHeadersEditor';
|
||||
import ContentTypeDropdown from './dropdowns/ContentTypeDropdown';
|
||||
@ -9,11 +8,11 @@ import BodyEditor from './editors/BodyEditor';
|
||||
import AuthEditor from './editors/AuthEditor';
|
||||
import {UrlBar} from './UrlBar.elm';
|
||||
import ElmComponent from './ElmComponent';
|
||||
|
||||
import {getContentTypeName} from '../../backend/contentTypes';
|
||||
import {getContentTypeFromHeaders} from '../../backend/contentTypes';
|
||||
import {
|
||||
getContentTypeName,
|
||||
getContentTypeFromHeaders
|
||||
} from '../../backend/contentTypes';
|
||||
import {MOD_SYM} from '../../backend/constants';
|
||||
import {trackEvent} from '../../backend/analytics';
|
||||
import {debounce} from '../lib/debounce';
|
||||
|
||||
class RequestPane extends Component {
|
||||
@ -104,31 +103,27 @@ class RequestPane extends Component {
|
||||
<Tabs className="pane__body">
|
||||
<TabList>
|
||||
<Tab>
|
||||
<button
|
||||
onClick={e => trackEvent('Request Tab Clicked', {name: 'Body'})}>
|
||||
<button>
|
||||
{getContentTypeName(getContentTypeFromHeaders(request.headers))}
|
||||
</button>
|
||||
<ContentTypeDropdown
|
||||
updateRequestContentType={updateRequestContentType}/>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<button
|
||||
onClick={e => trackEvent('Request Tab Clicked', {name: 'Auth'})}>
|
||||
<button>
|
||||
Auth {request.authentication.username ?
|
||||
<i className="fa fa-lock txt-sm"></i> : ''}
|
||||
</button>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<button
|
||||
onClick={e => trackEvent('Request Tab Clicked', {name: 'Params'})}>
|
||||
<button>
|
||||
Query {request.parameters.length ?
|
||||
<span
|
||||
className="txt-sm">({request.parameters.length})</span> : null}
|
||||
</button>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<button
|
||||
onClick={e => trackEvent('Request Tab Clicked', {name: 'Headers'})}>
|
||||
<button>
|
||||
Headers {request.headers.length ? (
|
||||
<span
|
||||
className="txt-sm">({request.headers.length})</span> ) : null}
|
||||
|
@ -11,11 +11,13 @@ import {
|
||||
getPreviewModeName,
|
||||
PREVIEW_MODE_SOURCE
|
||||
} from '../../backend/previewModes';
|
||||
import {REQUEST_TIME_TO_SHOW_COUNTER, MOD_SYM} from '../../backend/constants';
|
||||
import {trackEvent} from '../../backend/analytics';
|
||||
import {
|
||||
REQUEST_TIME_TO_SHOW_COUNTER,
|
||||
MOD_SYM,
|
||||
RESPONSE_CODE_DESCRIPTIONS
|
||||
} from '../../backend/constants';
|
||||
import {getSetCookieHeaders} from '../../backend/util';
|
||||
import {cancelCurrentRequest} from '../../backend/network';
|
||||
import {RESPONSE_CODE_DESCRIPTIONS} from '../../backend/constants';
|
||||
|
||||
class ResponsePane extends Component {
|
||||
constructor (props) {
|
||||
@ -165,8 +167,7 @@ class ResponsePane extends Component {
|
||||
<Tabs className="pane__body">
|
||||
<TabList>
|
||||
<Tab>
|
||||
<button
|
||||
onClick={e => trackEvent('Response Tab Clicked', {name: 'Body'})}>
|
||||
<button>
|
||||
{getPreviewModeName(previewMode)}
|
||||
</button>
|
||||
<PreviewModeDropdown
|
||||
@ -175,8 +176,7 @@ class ResponsePane extends Component {
|
||||
/>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<button
|
||||
onClick={e => trackEvent('Cookies Tab Clicked', {name: 'Cookies'})}>
|
||||
<button>
|
||||
Cookies {cookieHeaders.length ? (
|
||||
<span className="txt-sm">
|
||||
({cookieHeaders.length})
|
||||
@ -185,8 +185,7 @@ class ResponsePane extends Component {
|
||||
</button>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<button
|
||||
onClick={e => trackEvent('Response Tab Clicked', {name: 'Headers'})}>
|
||||
<button>
|
||||
Headers {response.headers.length ? (
|
||||
<span className="txt-sm">
|
||||
({response.headers.length})
|
||||
|
@ -42,7 +42,6 @@ import {getModal} from '../modals/index';
|
||||
import AlertModal from '../modals/AlertModal';
|
||||
import Link from '../base/Link';
|
||||
import {DEBOUNCE_MILLIS} from '../../../backend/constants';
|
||||
import {trackEvent} from '../../../backend/analytics';
|
||||
|
||||
|
||||
const BASE_CODEMIRROR_OPTIONS = {
|
||||
@ -159,7 +158,6 @@ class Editor extends Component {
|
||||
|
||||
_handleBeautify () {
|
||||
this._prettify(this.codeMirror.getValue());
|
||||
trackEvent('Beautify', {mode: this.props.mode});
|
||||
}
|
||||
|
||||
async _prettify (code) {
|
||||
|
@ -1,8 +1,6 @@
|
||||
import React, {PropTypes} from 'react';
|
||||
|
||||
import Dropdown from '../base/Dropdown';
|
||||
import {CONTENT_TYPES, getContentTypeName} from '../../../backend/contentTypes';
|
||||
import {trackEvent} from '../../../backend/analytics';
|
||||
|
||||
const ContentTypeDropdown = ({updateRequestContentType}) => {
|
||||
return (
|
||||
@ -14,7 +12,6 @@ const ContentTypeDropdown = ({updateRequestContentType}) => {
|
||||
{CONTENT_TYPES.map(contentType => (
|
||||
<li key={contentType}>
|
||||
<button onClick={e => {
|
||||
trackEvent('Changed Content-Type', {contentType});
|
||||
updateRequestContentType(contentType)
|
||||
}}>{getContentTypeName(contentType)}</button>
|
||||
</li>
|
||||
|
@ -1,8 +1,6 @@
|
||||
import React, {PropTypes} from 'react';
|
||||
|
||||
import Dropdown from '../base/Dropdown';
|
||||
import {PREVIEW_MODES, getPreviewModeName} from '../../../backend/previewModes';
|
||||
import {trackEvent} from '../../../backend/analytics';
|
||||
|
||||
const PreviewModeDropdown = ({updatePreviewMode}) => (
|
||||
<Dropdown>
|
||||
@ -13,7 +11,6 @@ const PreviewModeDropdown = ({updatePreviewMode}) => (
|
||||
{PREVIEW_MODES.map(previewMode => (
|
||||
<li key={previewMode}>
|
||||
<button onClick={() => {
|
||||
trackEvent('Changed Preview Mode', {previewMode});
|
||||
updatePreviewMode(previewMode);
|
||||
}}>{getPreviewModeName(previewMode)}</button>
|
||||
</li>
|
||||
|
@ -6,7 +6,7 @@ import ModalHeader from '../base/ModalHeader';
|
||||
import ModalBody from '../base/ModalBody';
|
||||
import MethodTag from '../tags/MethodTag';
|
||||
import * as db from '../../../backend/database';
|
||||
import {trackEvent} from '../../../backend/analytics';
|
||||
import {trackLegacyEvent} from '../../../backend/analytics';
|
||||
|
||||
|
||||
class RequestSwitcherModal extends Component {
|
||||
@ -165,7 +165,7 @@ class RequestSwitcherModal extends Component {
|
||||
}
|
||||
|
||||
show () {
|
||||
trackEvent('Show Quick Switcher');
|
||||
trackEvent('Modal', 'Show', 'Quick Switcher');
|
||||
this.modal.show();
|
||||
this._handleChange('');
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ import * as GlobalActions from '../redux/modules/global';
|
||||
import * as RequestActions from '../redux/modules/requests';
|
||||
import * as db from '../../backend/database';
|
||||
import {importCurl} from '../../backend/export/curl';
|
||||
import {trackEvent} from '../../backend/analytics';
|
||||
import {trackLegacyEvent} from '../../backend/analytics';
|
||||
import {getAppVersion} from '../../backend/appInfo';
|
||||
import {getModal} from '../components/modals/index';
|
||||
|
||||
@ -420,14 +420,14 @@ class App extends Component {
|
||||
});
|
||||
|
||||
// Do The Analytics
|
||||
trackEvent('App Launched');
|
||||
trackLegacyEvent('App Launched');
|
||||
|
||||
// Update Stats Object
|
||||
const {lastVersion, launches} = await db.stats.get();
|
||||
const firstLaunch = !lastVersion;
|
||||
if (firstLaunch) {
|
||||
// TODO: Show a welcome message
|
||||
trackEvent('First Launch');
|
||||
trackLegacyEvent('First Launch');
|
||||
} else if (lastVersion !== getAppVersion()) {
|
||||
getModal(ChangelogModal).show();
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ import {initStore} from './redux/initstore';
|
||||
import {initDB} from '../backend/database';
|
||||
import {initSync} from '../backend/sync';
|
||||
import {getAppVersion} from '../backend/appInfo';
|
||||
import {initAnalytics} from '../backend/analytics';
|
||||
import {initLegacyAnalytics} from '../backend/analytics';
|
||||
import {initAnalytics} from '../backend/ganalytics';
|
||||
|
||||
// Don't inject component styles (use our own)
|
||||
Tabs.setUseDefaultStyles(false);
|
||||
@ -29,6 +30,7 @@ console.log(`-- Loading App v${getAppVersion()} --`);
|
||||
await initSync();
|
||||
await initStore(store.dispatch);
|
||||
await initAnalytics();
|
||||
await initLegacyAnalytics();
|
||||
console.log('-- Rendering App --');
|
||||
render(
|
||||
<Provider store={store}><App /></Provider>,
|
||||
|
@ -3,7 +3,7 @@ import {combineReducers} from 'redux';
|
||||
import fs from 'fs';
|
||||
|
||||
import {importJSON, exportJSON} from '../../../backend/export/database';
|
||||
import {trackEvent} from '../../../backend/analytics';
|
||||
import {trackEvent} from '../../../backend/ganalytics';
|
||||
|
||||
const LOAD_START = 'global/load-start';
|
||||
const LOAD_STOP = 'global/load-stop';
|
||||
@ -123,7 +123,7 @@ export function importFile (workspace) {
|
||||
if (!paths) {
|
||||
// It was cancelled, so let's bail out
|
||||
dispatch(loadStop());
|
||||
trackEvent('Import Cancel');
|
||||
trackEvent('import', 'Cancel');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -133,13 +133,13 @@ export function importFile (workspace) {
|
||||
dispatch(loadStop());
|
||||
|
||||
if (err) {
|
||||
trackEvent('Import Fail');
|
||||
trackEvent('Import', 'Failure');
|
||||
console.warn('Import Failed', err);
|
||||
return;
|
||||
}
|
||||
|
||||
importJSON(workspace, data);
|
||||
trackEvent('Import');
|
||||
trackEvent('Import', 'Success');
|
||||
});
|
||||
})
|
||||
});
|
||||
@ -200,7 +200,7 @@ export function exportFile (parentDoc = null) {
|
||||
|
||||
electron.remote.dialog.showSaveDialog(options, filename => {
|
||||
if (!filename) {
|
||||
trackEvent('Export Cancel');
|
||||
trackEvent('Export', 'Cancel');
|
||||
// It was cancelled, so let's bail out
|
||||
dispatch(loadStop());
|
||||
return;
|
||||
@ -209,10 +209,10 @@ export function exportFile (parentDoc = null) {
|
||||
fs.writeFile(filename, json, {}, err => {
|
||||
if (err) {
|
||||
console.warn('Export failed', err);
|
||||
trackEvent('Export Fail');
|
||||
trackEvent('Export', 'Failure');
|
||||
return;
|
||||
}
|
||||
trackEvent('Export');
|
||||
trackEvent('Export', 'Success');
|
||||
dispatch(loadStop());
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,8 @@
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import {trackEvent} from '../../../backend/analytics';
|
||||
import {trackLegacyEvent} from '../../../backend/analytics';
|
||||
import * as network from '../../../backend/network';
|
||||
import {trackEvent} from '../../../backend/ganalytics';
|
||||
|
||||
export const REQUEST_SEND_START = 'requests/start';
|
||||
export const REQUEST_SEND_STOP = 'requests/stop';
|
||||
@ -44,7 +45,8 @@ export function send(request) {
|
||||
return async function (dispatch) {
|
||||
dispatch({type: REQUEST_SEND_START, requestId: request._id});
|
||||
|
||||
trackEvent('Request Send');
|
||||
trackEvent('Request', 'Send');
|
||||
trackLegacyEvent('Request Send');
|
||||
|
||||
try {
|
||||
await network.send(request._id);
|
||||
|
@ -61,11 +61,13 @@
|
||||
"classnames": "^2.2.3",
|
||||
"codemirror": "^5.18.2",
|
||||
"electron-context-menu": "^0.4.0",
|
||||
"electron-cookies": "^1.1.0",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"hkdf": "0.0.2",
|
||||
"httpsnippet": "git@github.com:getinsomnia/httpsnippet.git#a3a2c0a0167fa844bf92df52a1442fa1d68a9053",
|
||||
"json-lint": "^0.1.0",
|
||||
"jsonpath-plus": "^0.15.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mousetrap": "^1.6.0",
|
||||
"nedb": "^1.8.0",
|
||||
"node-forge": "^0.6.43",
|
||||
|
@ -10,7 +10,7 @@ echo "-- Creating Release $APP_VERSION --"
|
||||
# Create a new release #
|
||||
# ~~~~~~~~~~~~~~~~~~~~ #
|
||||
|
||||
curl https://app.getsentry.com/api/0/projects/schierco/insomnia-electron/releases/ \
|
||||
curl https://app.getsentry.com/api/0/projects/schierco/insomnia-app/releases/ \
|
||||
-X POST \
|
||||
-u "$SENTRY_TOKEN:" \
|
||||
-H 'Content-Type: application/json' \
|
||||
@ -23,20 +23,20 @@ echo "-- Uploading Source Maps for $APP_VERSION --"
|
||||
# Upload files for the given release #
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
||||
|
||||
curl https://app.getsentry.com/api/0/projects/schierco/insomnia-electron/releases/${APP_VERSION}/files/ \
|
||||
curl https://app.getsentry.com/api/0/projects/schierco/insomnia-app/releases/${APP_VERSION}/files/ \
|
||||
-X POST \
|
||||
-u "$SENTRY_TOKEN:" \
|
||||
-F file=@./build/bundle.js \
|
||||
-F name="bundle.js"
|
||||
|
||||
curl https://app.getsentry.com/api/0/projects/schierco/insomnia-electron/releases/${APP_VERSION}/files/ \
|
||||
curl https://app.getsentry.com/api/0/projects/schierco/insomnia-app/releases/${APP_VERSION}/files/ \
|
||||
-X POST \
|
||||
-u "$SENTRY_TOKEN:" \
|
||||
-F file=@./build/bundle.js \
|
||||
-F name="bundle.js"
|
||||
|
||||
# Upload a file for the given release
|
||||
curl https://app.getsentry.com/api/0/projects/schierco/insomnia-electron/releases/${APP_VERSION}/files/ \
|
||||
curl https://app.getsentry.com/api/0/projects/schierco/insomnia-app/releases/${APP_VERSION}/files/ \
|
||||
-X POST \
|
||||
-u "$SENTRY_TOKEN:" \
|
||||
-F file=@./build/bundle.js.map \
|
||||
|
Loading…
Reference in New Issue
Block a user