mirror of
https://github.com/balena-io/etcher.git
synced 2025-11-09 10:28:32 +00:00
Compare commits
1 Commits
v1.14.1
...
aethernet/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec7e0b745e |
37
.github/actions/publish/action.yml
vendored
37
.github/actions/publish/action.yml
vendored
@@ -72,6 +72,29 @@ runs:
|
||||
chmod +x "$(dirname "$(which node)")/resinci-deploy" && which resinci-deploy
|
||||
fi
|
||||
|
||||
# Upload sourcemaps to sentry
|
||||
- name: Generate Sentry DSN
|
||||
id: sentry
|
||||
shell: bash --noprofile --norc -eo pipefail -x {0}
|
||||
run: |
|
||||
set -ea
|
||||
|
||||
[[ '${{ inputs.VERBOSE }}' =~ on|On|Yes|yes|true|True ]] && set -x
|
||||
|
||||
branch="$(echo '${{ github.event.pull_request.head.ref }}' | sed 's/[^[:alnum:]]/-/g')"
|
||||
|
||||
stdout="$(resinci-deploy store sentry \
|
||||
--branch="${branch}" \
|
||||
--name="$(jq -r '.name' package.json)" \
|
||||
--team="$(yq e '.sentry.team' repo.yml)" \
|
||||
--org="$(yq e '.sentry.org' repo.yml)" \
|
||||
--type="$(yq e '.sentry.type' repo.yml)")"
|
||||
|
||||
echo "dsn=$(echo "${stdout}" | tail -n 1)" >> $GITHUB_OUTPUT
|
||||
|
||||
env:
|
||||
SENTRY_TOKEN: ${{ fromJSON(inputs.secrets).SENTRY_AUTH_TOKEN }}
|
||||
|
||||
# https://www.electron.build/code-signing.html
|
||||
# https://github.com/Apple-Actions/import-codesign-certs
|
||||
- name: Import Apple code signing certificate
|
||||
@@ -145,8 +168,8 @@ runs:
|
||||
|
||||
for target in ${TARGETS}; do
|
||||
electron-builder ${ELECTRON_BUILDER_OS} ${target} ${ARCHITECTURE_FLAGS} \
|
||||
--c.extraMetadata.analytics.sentry.token='https://739bbcfc0ba4481481138d3fc831136d@o95242.ingest.sentry.io/4504451487301632' \
|
||||
--c.extraMetadata.analytics.amplitude.token='balena-etcher' \
|
||||
--c.extraMetadata.analytics.sentry.token='${{ steps.sentry.outputs.dsn }}' \
|
||||
--c.extraMetadata.analytics.mixpanel.token='balena-etcher' \
|
||||
--c.extraMetadata.packageType="${target}"
|
||||
|
||||
find dist -type f -maxdepth 1
|
||||
@@ -180,6 +203,16 @@ runs:
|
||||
-name "latest*.yml" \
|
||||
-exec yq -i e .stagingPercentage=\"$percentage\" {} \;
|
||||
|
||||
- name: Upload sourcemap to Sentry
|
||||
shell: bash --noprofile --norc -eo pipefail -x {0}
|
||||
run: |
|
||||
VERSION=${{ steps.package_release.outputs.version }} npm run uploadSourcemap
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ fromJSON(inputs.secrets).SENTRY_AUTH_TOKEN }}
|
||||
npm_config_SENTRY_ORG: balenaEtcher
|
||||
npm_config_SENTRY_PROJECT: balenaetcher
|
||||
npm_config_SENTRY_VERSION: ${{ steps.package_release.outputs.version }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
||||
@@ -1,69 +1,3 @@
|
||||
- commits:
|
||||
- subject: fix disabled-screensaver unhandled exception outside balena-electron env
|
||||
hash: 46c406e8c1e3b5e41890aff7f65b1711e4426782
|
||||
body: ""
|
||||
footer:
|
||||
Change-type: patch
|
||||
change-type: patch
|
||||
author: Edwin Joassart
|
||||
nested: []
|
||||
version: 1.14.1
|
||||
title: ""
|
||||
date: 2023-01-16T13:22:36.972Z
|
||||
- commits:
|
||||
- subject: Anonymizes all paths before sending
|
||||
hash: 86d43a536f7c9aa6b450a9f2f90341e07364208e
|
||||
body: ""
|
||||
footer:
|
||||
Change-type: patch
|
||||
change-type: patch
|
||||
author: Otávio Jacobi
|
||||
nested: []
|
||||
- subject: "patch: Sentry fix path"
|
||||
hash: 6c417e35a13873cd95d25f42a819de3750cdf65d
|
||||
body: ""
|
||||
footer: {}
|
||||
author: Edwin Joassart
|
||||
nested: []
|
||||
- subject: Remove personal path on etcher
|
||||
hash: 2b728d3c521b76177a2c019b4891627272f35aac
|
||||
body: ""
|
||||
footer:
|
||||
Change-type: minor
|
||||
change-type: minor
|
||||
author: Otávio Jacobi
|
||||
nested: []
|
||||
- subject: Unifying sentry reports in a single project
|
||||
hash: f3f7ecb852503d4d97dbe6a78bf920ca177bddd1
|
||||
body: ""
|
||||
footer:
|
||||
Change-type: patch
|
||||
change-type: patch
|
||||
author: Edwin Joassart
|
||||
nested: []
|
||||
- subject: Removes corvus in favor of sentry and analytics client
|
||||
hash: 41fca03c98d4a72bd8c3842d7e6b9d41f65336f9
|
||||
body: ""
|
||||
footer:
|
||||
Change-type: patch
|
||||
change-type: patch
|
||||
Signed-off-by: Otavio Jacobi
|
||||
signed-off-by: Otavio Jacobi
|
||||
author: Otávio Jacobi
|
||||
nested: []
|
||||
- subject: Removes corvus in favor of sentry and analytics client
|
||||
hash: 10caf8f1b6a174762192b13ce7bb4eaa71e90fcc
|
||||
body: ""
|
||||
footer:
|
||||
Change-type: patch
|
||||
change-type: patch
|
||||
Signed-off-by: Otavio Jacobi
|
||||
signed-off-by: Otavio Jacobi
|
||||
author: Otávio Jacobi
|
||||
nested: []
|
||||
version: 1.14.0
|
||||
title: ""
|
||||
date: 2023-01-16T11:23:54.866Z
|
||||
- commits:
|
||||
- subject: Adding EtcherPro device serial number to the Settings modal
|
||||
hash: d25eda9a7d6bf89284b630b2d55cbb0a7e3a9432
|
||||
|
||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -3,21 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# v1.14.1
|
||||
## (2023-01-16)
|
||||
|
||||
* fix disabled-screensaver unhandled exception outside balena-electron env [Edwin Joassart]
|
||||
|
||||
# v1.14.0
|
||||
## (2023-01-16)
|
||||
|
||||
* Anonymizes all paths before sending [Otávio Jacobi]
|
||||
* patch: Sentry fix path [Edwin Joassart]
|
||||
* Remove personal path on etcher [Otávio Jacobi]
|
||||
* Unifying sentry reports in a single project [Edwin Joassart]
|
||||
* Removes corvus in favor of sentry and analytics client [Otávio Jacobi]
|
||||
* Removes corvus in favor of sentry and analytics client [Otávio Jacobi]
|
||||
|
||||
# v1.13.4
|
||||
## (2023-01-12)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Releasing
|
||||
- [Post release note to forums](https://forums.balena.io/c/etcher)
|
||||
- [Submit Windows binaries to Symantec for whitelisting](#submitting-binaries-to-symantec)
|
||||
- [Update the website](https://github.com/balena-io/etcher-homepage)
|
||||
- Wait 2-3 hours for analytics (Sentry, Amplitude) to trickle in and check for elevated error rates, or regressions
|
||||
- Wait 2-3 hours for analytics (Sentry, Mixpanel) to trickle in and check for elevated error rates, or regressions
|
||||
- If regressions arise; pull the release, and release a patched version, else:
|
||||
- [Upload deb & rpm packages to Bintray](#uploading-packages-to-bintray)
|
||||
- [Upload build artifacts to Amazon S3](#uploading-binaries-to-amazon-s3)
|
||||
@@ -48,7 +48,7 @@ Make sure to set the analytics tokens when generating production release binarie
|
||||
|
||||
```bash
|
||||
export ANALYTICS_SENTRY_TOKEN="xxxxxx"
|
||||
export ANALYTICS_AMPLITUDE_TOKEN="xxxxxx"
|
||||
export ANALYTICS_MIXPANEL_TOKEN="xxxxxx"
|
||||
```
|
||||
|
||||
#### Linux
|
||||
|
||||
@@ -112,4 +112,4 @@ Analytics
|
||||
- [ ] Disable analytics, open DevTools Network pane or a packet sniffer, and
|
||||
check that no request is sent
|
||||
- [ ] **Disable analytics, refresh application from DevTools (using Cmd-R or
|
||||
F5), and check that initial events are not sent to Amplitude**
|
||||
F5), and check that initial events are not sent to Mixpanel**
|
||||
|
||||
@@ -296,8 +296,6 @@ driveScanner.start();
|
||||
|
||||
let popupExists = false;
|
||||
|
||||
analytics.initAnalytics();
|
||||
|
||||
window.addEventListener('beforeunload', async (event) => {
|
||||
if (!flashState.isFlashing() || popupExists) {
|
||||
analytics.logEvent('Close application', {
|
||||
|
||||
@@ -183,12 +183,7 @@ export class SafeWebview extends React.PureComponent<
|
||||
// only care about this event if it's a request for the main frame
|
||||
if (event.resourceType === 'mainFrame') {
|
||||
const HTTP_OK = 200;
|
||||
const { webContents, ...webviewEvent } = event;
|
||||
analytics.logEvent('SafeWebview loaded', {
|
||||
...webviewEvent,
|
||||
screen_height: webContents?.hostWebContents.browserWindowOptions.height,
|
||||
screen_width: webContents?.hostWebContents.browserWindowOptions.width,
|
||||
});
|
||||
analytics.logEvent('SafeWebview loaded', { event });
|
||||
this.setState({
|
||||
shouldShow: event.statusCode === HTTP_OK,
|
||||
});
|
||||
|
||||
@@ -47,13 +47,7 @@ export function isFlashing(): boolean {
|
||||
*/
|
||||
export function setFlashingFlag() {
|
||||
// see https://github.com/balenablocks/balena-electron-env/blob/4fce9c461f294d4a768db8f247eea6f75d7b08b0/README.md#remote-methods
|
||||
try {
|
||||
electron.ipcRenderer.invoke('disable-screensaver');
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"Can't disable-screensaver, we're probably not running on a balena-electron env",
|
||||
);
|
||||
}
|
||||
electron.ipcRenderer.invoke('disable-screensaver');
|
||||
store.dispatch({
|
||||
type: Actions.SET_FLASHING_FLAG,
|
||||
data: {},
|
||||
|
||||
@@ -15,188 +15,84 @@
|
||||
*/
|
||||
|
||||
import * as _ from 'lodash';
|
||||
import { Client, createClient, createNoopClient } from 'analytics-client';
|
||||
import * as SentryRenderer from '@sentry/electron/renderer';
|
||||
import * as resinCorvus from 'resin-corvus/browser';
|
||||
|
||||
import * as packageJSON from '../../../../package.json';
|
||||
import { getConfig } from '../../../shared/utils';
|
||||
import * as settings from '../models/settings';
|
||||
import { store } from '../models/store';
|
||||
import * as packageJSON from '../../../../package.json';
|
||||
|
||||
type AnalyticsPayload = _.Dictionary<any>;
|
||||
const DEFAULT_PROBABILITY = 0.1;
|
||||
|
||||
const clearUserPath = (filename: string): string => {
|
||||
const generatedFile = filename.split('generated').reverse()[0];
|
||||
return generatedFile !== filename ? `generated${generatedFile}` : filename;
|
||||
};
|
||||
|
||||
export const anonymizeSentryData = (
|
||||
event: SentryRenderer.Event,
|
||||
): SentryRenderer.Event => {
|
||||
event.exception?.values?.forEach((exception) => {
|
||||
exception.stacktrace?.frames?.forEach((frame) => {
|
||||
if (frame.filename) {
|
||||
frame.filename = clearUserPath(frame.filename);
|
||||
}
|
||||
});
|
||||
async function installCorvus(): Promise<void> {
|
||||
const sentryToken =
|
||||
(await settings.get('analyticsSentryToken')) ||
|
||||
_.get(packageJSON, ['analytics', 'sentry', 'token']);
|
||||
const mixpanelToken =
|
||||
(await settings.get('analyticsMixpanelToken')) ||
|
||||
_.get(packageJSON, ['analytics', 'mixpanel', 'token']);
|
||||
resinCorvus.install({
|
||||
services: {
|
||||
sentry: sentryToken,
|
||||
mixpanel: mixpanelToken,
|
||||
},
|
||||
options: {
|
||||
release: packageJSON.version,
|
||||
shouldReport: () => {
|
||||
return settings.getSync('errorReporting');
|
||||
},
|
||||
mixpanelDeferred: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
event.breadcrumbs?.forEach((breadcrumb) => {
|
||||
if (breadcrumb.data?.url) {
|
||||
breadcrumb.data.url = clearUserPath(breadcrumb.data.url);
|
||||
}
|
||||
});
|
||||
let mixpanelSample = DEFAULT_PROBABILITY;
|
||||
|
||||
if (event.request?.url) {
|
||||
event.request.url = clearUserPath(event.request.url);
|
||||
}
|
||||
|
||||
return event;
|
||||
};
|
||||
|
||||
const extractPathRegex = /(.*)(^|\s)(file\:\/\/)?(\w\:)?([\\\/].+)/;
|
||||
const etcherSegmentMarkers = ['app.asar', 'Resources'];
|
||||
|
||||
export const anonymizePath = (input: string) => {
|
||||
// First, extract a part of the value that matches a path pattern.
|
||||
const match = extractPathRegex.exec(input);
|
||||
if (match === null) {
|
||||
return input;
|
||||
}
|
||||
const mainPart = match[5];
|
||||
const space = match[2];
|
||||
const beginning = match[1];
|
||||
const uriPrefix = match[3] || '';
|
||||
|
||||
// We have to deal with both Windows and POSIX here.
|
||||
// The path starts with its separator (we work with absolute paths).
|
||||
const sep = mainPart[0];
|
||||
const segments = mainPart.split(sep);
|
||||
|
||||
// Moving from the end, find the first marker and cut the path from there.
|
||||
const startCutIndex = _.findLastIndex(segments, (segment) =>
|
||||
etcherSegmentMarkers.includes(segment),
|
||||
);
|
||||
return (
|
||||
beginning +
|
||||
space +
|
||||
uriPrefix +
|
||||
'[PERSONAL PATH]' +
|
||||
sep +
|
||||
segments.splice(startCutIndex).join(sep)
|
||||
);
|
||||
};
|
||||
|
||||
const safeAnonymizePath = (input: string) => {
|
||||
try {
|
||||
return anonymizePath(input);
|
||||
} catch (e) {
|
||||
return '[ANONYMIZE PATH FAILED]';
|
||||
}
|
||||
};
|
||||
|
||||
const sensitiveEtcherProperties = [
|
||||
'error.description',
|
||||
'error.message',
|
||||
'error.stack',
|
||||
'image',
|
||||
'image.path',
|
||||
'path',
|
||||
];
|
||||
|
||||
export const anonymizeAnalyticsPayload = (
|
||||
data: AnalyticsPayload,
|
||||
): AnalyticsPayload => {
|
||||
for (const prop of sensitiveEtcherProperties) {
|
||||
const value = data[prop];
|
||||
if (value != null) {
|
||||
data[prop] = safeAnonymizePath(value.toString());
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
let analyticsClient: Client;
|
||||
/**
|
||||
* @summary Init analytics configurations
|
||||
*/
|
||||
export const initAnalytics = _.once(() => {
|
||||
const dsn =
|
||||
settings.getSync('analyticsSentryToken') ||
|
||||
_.get(packageJSON, ['analytics', 'sentry', 'token']);
|
||||
SentryRenderer.init({ dsn, beforeSend: anonymizeSentryData });
|
||||
|
||||
const projectName =
|
||||
settings.getSync('analyticsAmplitudeToken') ||
|
||||
_.get(packageJSON, ['analytics', 'amplitude', 'token']);
|
||||
|
||||
const clientConfig = {
|
||||
projectName,
|
||||
endpoint: 'data.balena-cloud.com',
|
||||
componentName: 'etcher',
|
||||
componentVersion: packageJSON.version,
|
||||
};
|
||||
analyticsClient = projectName
|
||||
? createClient(clientConfig)
|
||||
: createNoopClient();
|
||||
});
|
||||
|
||||
const getCircularReplacer = () => {
|
||||
const seen = new WeakSet();
|
||||
return (key: any, value: any) => {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
if (seen.has(value)) {
|
||||
return;
|
||||
}
|
||||
seen.add(value);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
};
|
||||
|
||||
function flattenObject(obj: any) {
|
||||
const toReturn: AnalyticsPayload = {};
|
||||
|
||||
for (const i in obj) {
|
||||
if (!obj.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(obj[i])) {
|
||||
toReturn[i] = obj[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof obj[i] === 'object' && obj[i] !== null) {
|
||||
const flatObject = flattenObject(obj[i]);
|
||||
for (const x in flatObject) {
|
||||
if (!flatObject.hasOwnProperty(x)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
toReturn[i.toLowerCase() + '.' + x.toLowerCase()] = flatObject[x];
|
||||
}
|
||||
} else {
|
||||
toReturn[i] = obj[i];
|
||||
async function initConfig() {
|
||||
await installCorvus();
|
||||
let validatedConfig = null;
|
||||
try {
|
||||
const configUrl = await settings.get('configUrl');
|
||||
const config = await getConfig(configUrl);
|
||||
const mixpanel = _.get(config, ['analytics', 'mixpanel'], {});
|
||||
mixpanelSample = mixpanel.probability || DEFAULT_PROBABILITY;
|
||||
if (isClientEligible(mixpanelSample)) {
|
||||
validatedConfig = validateMixpanelConfig(mixpanel);
|
||||
}
|
||||
} catch (err) {
|
||||
resinCorvus.logException(err);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
function formatEvent(data: any): AnalyticsPayload {
|
||||
const event = JSON.parse(JSON.stringify(data, getCircularReplacer()));
|
||||
return anonymizeAnalyticsPayload(flattenObject(event));
|
||||
}
|
||||
|
||||
function reportAnalytics(message: string, data: AnalyticsPayload = {}) {
|
||||
const { applicationSessionUuid, flashingWorkflowUuid } = store
|
||||
.getState()
|
||||
.toJS();
|
||||
|
||||
const event = formatEvent({
|
||||
...data,
|
||||
applicationSessionUuid,
|
||||
flashingWorkflowUuid,
|
||||
resinCorvus.setConfigs({
|
||||
mixpanel: validatedConfig,
|
||||
});
|
||||
analyticsClient.track(message, event);
|
||||
}
|
||||
|
||||
initConfig();
|
||||
|
||||
/**
|
||||
* @summary Check that the client is eligible for analytics
|
||||
*/
|
||||
function isClientEligible(probability: number) {
|
||||
return Math.random() < probability;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Check that config has at least HTTP_PROTOCOL and api_host
|
||||
*/
|
||||
function validateMixpanelConfig(config: {
|
||||
api_host?: string;
|
||||
HTTP_PROTOCOL?: string;
|
||||
}) {
|
||||
const mixpanelConfig = {
|
||||
api_host: 'https://api.mixpanel.com',
|
||||
};
|
||||
if (config.HTTP_PROTOCOL !== undefined && config.api_host !== undefined) {
|
||||
mixpanelConfig.api_host = `${config.HTTP_PROTOCOL}://${config.api_host}`;
|
||||
}
|
||||
return mixpanelConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,12 +101,16 @@ function reportAnalytics(message: string, data: AnalyticsPayload = {}) {
|
||||
* @description
|
||||
* This function sends the debug message to product analytics services.
|
||||
*/
|
||||
export async function logEvent(message: string, data: AnalyticsPayload = {}) {
|
||||
const shouldReportAnalytics = await settings.get('errorReporting');
|
||||
if (shouldReportAnalytics) {
|
||||
initAnalytics();
|
||||
reportAnalytics(message, data);
|
||||
}
|
||||
export function logEvent(message: string, data: _.Dictionary<any> = {}) {
|
||||
const { applicationSessionUuid, flashingWorkflowUuid } = store
|
||||
.getState()
|
||||
.toJS();
|
||||
resinCorvus.logEvent(message, {
|
||||
...data,
|
||||
sample: mixpanelSample,
|
||||
applicationSessionUuid,
|
||||
flashingWorkflowUuid,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,11 +119,4 @@ export async function logEvent(message: string, data: AnalyticsPayload = {}) {
|
||||
* @description
|
||||
* This function logs an exception to error reporting services.
|
||||
*/
|
||||
export function logException(error: any) {
|
||||
const shouldReportErrors = settings.getSync('errorReporting');
|
||||
console.error(error);
|
||||
if (shouldReportErrors) {
|
||||
initAnalytics();
|
||||
SentryRenderer.captureException(error);
|
||||
}
|
||||
}
|
||||
export const logException = resinCorvus.logException;
|
||||
|
||||
@@ -20,7 +20,6 @@ import { promises as fs } from 'fs';
|
||||
import { platform } from 'os';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import './app/i18n';
|
||||
|
||||
@@ -28,11 +27,9 @@ import { packageType, version } from '../../package.json';
|
||||
import * as EXIT_CODES from '../shared/exit-codes';
|
||||
import { delay, getConfig } from '../shared/utils';
|
||||
import * as settings from './app/models/settings';
|
||||
import { logException } from './app/modules/analytics';
|
||||
import { buildWindowMenu } from './menu';
|
||||
import * as i18n from 'i18next';
|
||||
import * as SentryMain from '@sentry/electron/main';
|
||||
import * as packageJSON from '../../package.json';
|
||||
import { anonymizeSentryData } from './app/modules/analytics';
|
||||
|
||||
const customProtocol = 'etcher';
|
||||
const scheme = `${customProtocol}://`;
|
||||
@@ -56,21 +53,13 @@ async function checkForUpdates(interval: number) {
|
||||
packageUpdated = true;
|
||||
}
|
||||
} catch (err) {
|
||||
logMainProcessException(err);
|
||||
logException(err);
|
||||
}
|
||||
}
|
||||
await delay(interval);
|
||||
}
|
||||
}
|
||||
|
||||
function logMainProcessException(error: any) {
|
||||
const shouldReportErrors = settings.getSync('errorReporting');
|
||||
console.error(error);
|
||||
if (shouldReportErrors) {
|
||||
SentryMain.captureException(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function isFile(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
const stat = await fs.stat(filePath);
|
||||
@@ -105,14 +94,6 @@ async function getCommandLineURL(argv: string[]): Promise<string | undefined> {
|
||||
}
|
||||
}
|
||||
|
||||
const initSentryMain = _.once(() => {
|
||||
const dsn =
|
||||
settings.getSync('analyticsSentryToken') ||
|
||||
_.get(packageJSON, ['analytics', 'sentry', 'token']);
|
||||
|
||||
SentryMain.init({ dsn, beforeSend: anonymizeSentryData });
|
||||
});
|
||||
|
||||
const sourceSelectorReady = new Promise((resolve) => {
|
||||
electron.ipcMain.on('source-selector-ready', resolve);
|
||||
});
|
||||
@@ -209,9 +190,8 @@ async function createMainWindow() {
|
||||
const page = mainWindow.webContents;
|
||||
|
||||
page.once('did-frame-finish-load', async () => {
|
||||
console.log('packageUpdatable', packageUpdatable);
|
||||
autoUpdater.on('error', (err) => {
|
||||
logMainProcessException(err);
|
||||
logException(err);
|
||||
});
|
||||
if (packageUpdatable) {
|
||||
try {
|
||||
@@ -228,7 +208,7 @@ async function createMainWindow() {
|
||||
onlineConfig?.autoUpdates?.checkForUpdatesTimer ?? 300000;
|
||||
checkForUpdates(checkForUpdatesTimer);
|
||||
} catch (err) {
|
||||
logMainProcessException(err);
|
||||
logException(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -253,7 +233,6 @@ async function main(): Promise<void> {
|
||||
if (!electron.app.requestSingleInstanceLock()) {
|
||||
electron.app.quit();
|
||||
} else {
|
||||
initSentryMain();
|
||||
await electron.app.whenReady();
|
||||
const window = await createMainWindow();
|
||||
electron.app.on('second-instance', async (_event, argv) => {
|
||||
@@ -277,6 +256,7 @@ async function main(): Promise<void> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
console.time('ready-to-show');
|
||||
|
||||
1083
package-lock.json
generated
1083
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
"name": "balena-etcher",
|
||||
"private": true,
|
||||
"displayName": "balenaEtcher",
|
||||
"version": "1.14.1",
|
||||
"version": "1.13.4",
|
||||
"packageType": "local",
|
||||
"main": "generated/etcher.js",
|
||||
"description": "Flash OS images to SD cards and USB drives, safely and easily.",
|
||||
@@ -31,6 +31,7 @@
|
||||
"test-spectron": "mocha --recursive --reporter spec --require ts-node/register/transpile-only --require-main tests/gui/allow-renderer-process-reuse.ts tests/spectron/runner.spec.ts",
|
||||
"test-windows": "npm run lint && npm run test-gui && npm run test-shared && npm run test-spectron && npm run sanity-checks",
|
||||
"test": "echo npm run test-{linux,windows,macos}",
|
||||
"uploadSourcemap": "sentry-cli releases files $npm_config_SENTRY_VERSION upload-sourcemaps ./generated/*.js.map --org $npm_config_SENTRY_ORG --project $npm_config_SENTRY_PROJECT",
|
||||
"watch": "webpack serve --no-optimization-minimize --config ./webpack.dev.config.ts",
|
||||
"webpack": "webpack"
|
||||
},
|
||||
@@ -53,7 +54,7 @@
|
||||
"@balena/lint": "5.4.2",
|
||||
"@balena/sudo-prompt": "9.2.1-workaround-windows-amperstand-in-username-0849e215b947987a643fe5763902aea201255534",
|
||||
"@fortawesome/fontawesome-free": "5.15.4",
|
||||
"@sentry/electron": "^4.1.2",
|
||||
"@sentry/cli": "^2.11.0",
|
||||
"@svgr/webpack": "5.5.0",
|
||||
"@types/chai": "4.3.4",
|
||||
"@types/copy-webpack-plugin": "6.4.3",
|
||||
@@ -69,7 +70,6 @@
|
||||
"@types/terser-webpack-plugin": "5.0.4",
|
||||
"@types/tmp": "0.2.3",
|
||||
"@types/webpack-node-externals": "2.5.3",
|
||||
"analytics-client": "^2.0.1",
|
||||
"aws4-axios": "2.4.9",
|
||||
"chai": "4.3.7",
|
||||
"copy-webpack-plugin": "7.0.0",
|
||||
@@ -104,6 +104,7 @@
|
||||
"react-i18next": "11.18.6",
|
||||
"redux": "4.2.0",
|
||||
"rendition": "19.3.2",
|
||||
"resin-corvus": "2.0.5",
|
||||
"semver": "7.3.8",
|
||||
"simple-progress-webpack-plugin": "1.1.2",
|
||||
"sinon": "9.2.4",
|
||||
@@ -127,6 +128,6 @@
|
||||
"node": ">=14 < 16"
|
||||
},
|
||||
"versionist": {
|
||||
"publishedAt": "2023-01-16T13:22:37.656Z"
|
||||
"publishedAt": "2023-01-12T15:10:50.986Z"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import * as PnpWebpackPlugin from 'pnp-webpack-plugin';
|
||||
import * as tsconfigRaw from './tsconfig.webpack.json';
|
||||
|
||||
/**
|
||||
* Don't webpack package.json as sentry tokens
|
||||
* Don't webpack package.json as mixpanel & sentry tokens
|
||||
* will be inserted in it after webpacking
|
||||
*/
|
||||
function externalPackageJson(packageJsonPath: string) {
|
||||
@@ -455,6 +455,7 @@ const guiConfig = {
|
||||
const mainConfig = {
|
||||
...commonConfig,
|
||||
target: 'electron-main',
|
||||
devtool: 'source-map',
|
||||
node: {
|
||||
__dirname: false,
|
||||
__filename: true,
|
||||
|
||||
Reference in New Issue
Block a user