diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4e935fbb..aabe0716 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: - name: Install run: yarn install - name: Build - run: yarn build + run: yarn start build - name: Pack run: yarn pack - name: Archive Artifacts @@ -49,7 +49,7 @@ jobs: node-version-file: 'package.json' - run: yarn install - name: Run Linter - run: yarn lint + run: yarn start lint test: name: Unit Tests @@ -70,7 +70,7 @@ jobs: - run: yarn install - name: Run Unit Tests timeout-minutes: 10 - run: yarn test + run: yarn start test e2e: name: E2E Tests @@ -93,7 +93,7 @@ jobs: - run: yarn install - name: Run E2E Tests timeout-minutes: 30 - run: yarn e2e + run: yarn start e2e required_jobs_passed: name: All required jobs passed or were skipped diff --git a/package.json b/package.json index e96bf2e6..6822ffcf 100644 --- a/package.json +++ b/package.json @@ -37,23 +37,7 @@ "access": "public" }, "scripts": { - "prebuild": "yarn clean && node scripts/update-version.js", - "build": "rollup --config rollup.config.mjs", - "postbuild": "node scripts/check-exports.mjs", - "clean": "rimraf --glob coverage common esm main preload renderer index.* sentry-electron*.tgz .eslintcache", - "prelint": "node scripts/update-version.js", - "lint": "run-s lint:prettier lint:eslint", - "lint:prettier": "prettier --check \"{src,test}/**/*.ts\"", - "lint:eslint": "eslint . --cache --format stylish", - "fix": "run-s fix:eslint fix:prettier", - "fix:prettier": "prettier --write \"{src,test}/**/*.ts\"", - "fix:eslint": "eslint . --format stylish --fix", - "update-electron-versions": "electron-latest-versions --start 15 --beta > ./test/e2e/versions.json", - "update-sdk-versions": "node ./scripts/update-sdk-versions.mjs", - "pretest": "yarn build", - "test": "vitest run --root=./test/unit", - "pree2e": "rimraf --glob test/e2e/dist/**/node_modules/@sentry/** test/e2e/dist/**/yarn.lock test/e2e/dist/**/package-lock.json && node scripts/clean-cache.js && yarn build && npm pack", - "e2e": "xvfb-maybe vitest run --root=./test/e2e --silent=false --disable-console-intercept" + "start": "node scripts/start.mjs" }, "dependencies": { "@sentry/browser": "8.0.0-beta.5", diff --git a/scripts/check-exports.mjs b/scripts/check-exports.mjs index b261437a..94be4ca4 100644 --- a/scripts/check-exports.mjs +++ b/scripts/check-exports.mjs @@ -3,49 +3,53 @@ import * as renderer from '../esm/renderer/index.js'; import * as node from '@sentry/node'; -// We need to shim electron to avoid errors when importing the main process code into plain-old-node that doesn't have -// the electron module built-in. -import './electron-shim.mjs'; - -const main = await import('../esm/main/index.js'); - -const browserExports = Object.keys(browser); -const rendererExports = Object.keys(renderer); -const nodeExports = Object.keys(node); -const mainExports = Object.keys(main); - -const ignoredBrowser = [ - 'SDK_VERSION', - 'WINDOW', - 'Integrations', - 'close', - 'flush', - 'defaultStackLineParsers', - // These wont ever be used - 'geckoStackLineParser', - 'opera10StackLineParser', - 'opera11StackLineParser', - 'winjsStackLineParser', - // If you use the browser transports, just use the browser SDK - 'makeBrowserOfflineTransport', - 'makeFetchTransport', - 'makeMultiplexedTransport', - 'lazyLoadIntegration', -]; - -const ignoredNode = ['SDK_VERSION', 'makeNodeTransport', 'getSentryRelease']; - -const missingRenderer = browserExports.filter((key) => !rendererExports.includes(key) && !ignoredBrowser.includes(key)); -const missingMain = nodeExports.filter((key) => !mainExports.includes(key) && !ignoredNode.includes(key)); - -if (missingRenderer.length || missingMain.length) { - if (missingRenderer.length) { - console.error('Missing renderer exports:', missingRenderer); +export default async function () { + // We need to shim electron to avoid errors when importing the main process code into plain-old-node that doesn't have + // the electron module built-in. + await import('./electron-shim.mjs'); + + const main = await import('../esm/main/index.js'); + + const browserExports = Object.keys(browser); + const rendererExports = Object.keys(renderer); + const nodeExports = Object.keys(node); + const mainExports = Object.keys(main); + + const ignoredBrowser = [ + 'SDK_VERSION', + 'WINDOW', + 'Integrations', + 'close', + 'flush', + 'defaultStackLineParsers', + // These wont ever be used + 'geckoStackLineParser', + 'opera10StackLineParser', + 'opera11StackLineParser', + 'winjsStackLineParser', + // If you use the browser transports, just use the browser SDK + 'makeBrowserOfflineTransport', + 'makeFetchTransport', + 'makeMultiplexedTransport', + 'lazyLoadIntegration', + ]; + + const ignoredNode = ['SDK_VERSION', 'makeNodeTransport', 'getSentryRelease']; + + const missingRenderer = browserExports.filter( + (key) => !rendererExports.includes(key) && !ignoredBrowser.includes(key), + ); + const missingMain = nodeExports.filter((key) => !mainExports.includes(key) && !ignoredNode.includes(key)); + + if (missingRenderer.length || missingMain.length) { + if (missingRenderer.length) { + console.error('⚠️ Missing renderer exports ⚠️\n', missingRenderer); + } + + if (missingMain.length) { + console.error('⚠️ Missing main exports ⚠️\n', missingMain); + } + + process.exit(1); } - - if (missingMain.length) { - console.error('Missing main exports:', missingMain); - } - - process.exit(1); } diff --git a/scripts/clean-cache.js b/scripts/clean-cache.js deleted file mode 100644 index c6241ec1..00000000 --- a/scripts/clean-cache.js +++ /dev/null @@ -1,14 +0,0 @@ -// Yarn has a bug where 'yarn cache clean @sentry/electron' does not -// remove the temp directory where the tgz is unpacked to. This means -// installing from local tgz does not update when src changes are made -// https://github.com/yarnpkg/yarn/issues/5357 - -const { spawnSync } = require('child_process'); -const { rmSync } = require('fs'); -const { join } = require('path'); - -spawnSync('yarn cache clean @sentry/electron', { shell: true, stdio: 'inherit' }); -const dirResult = spawnSync('yarn cache dir', { shell: true }); - -const tmpDir = join(dirResult.output.toString().replace(/[,\n\r]/g, ''), '.tmp'); -rmSync(tmpDir, { recursive: true, force: true }); diff --git a/scripts/start.mjs b/scripts/start.mjs new file mode 100644 index 00000000..98938da8 --- /dev/null +++ b/scripts/start.mjs @@ -0,0 +1,49 @@ +import updateVersion from './update-version.mjs'; +import updateSdkVersions from './update-sdk-versions.mjs'; +import checkPackageExports from './check-exports.mjs'; + +/** + * Each script is made up of one or more commands. + * + * Commands can be: + * - String commands to be executed in the shell + * - String that refers to another script + * - JavaScript functions (sync or async) + */ +scripts({ + clean: 'rimraf --glob coverage common esm main preload renderer index.* sentry-electron*.tgz .eslintcache', + build: ['clean', updateVersion, 'rollup --config rollup.config.mjs', checkPackageExports], + lint: [updateVersion, 'lint:prettier', 'lint:eslint'], + 'lint:prettier': 'prettier --check "{src,test}/**/*.ts"', + 'lint:eslint': 'eslint . --cache --format stylish', + fix: [updateVersion, 'fix:prettier', 'fix:eslint'], + 'fix:prettier': 'prettier --write "{src,test}/**/*.ts"', + 'fix:eslint': 'eslint . --cache --format --fix', + 'update-electron-versions': 'electron-latest-versions --start 15 --beta > ./test/e2e/versions.json', + 'update-sdk-versions': updateSdkVersions, + test: ['build', 'vitest run --root=./test/unit'], + e2e: [ + 'rimraf --glob test/e2e/dist/**/node_modules/@sentry/** test/e2e/dist/**/yarn.lock test/e2e/dist/**/package-lock.json', + 'yarn cache clean', + 'build', + 'npm pack', + 'xvfb-maybe vitest run --root=./test/e2e --silent=false --disable-console-intercept', + ], +}); + +import { execSync } from 'child_process'; + +function scripts(scripts) { + async function run(cmd) { + for (const next of Array.isArray(scripts[cmd]) ? scripts[cmd] : [scripts[cmd]]) { + if (typeof next === 'function') await next(); + else if (next in scripts) await run(next); + else { + console.log(`\n> ${next}`); + execSync(next, { stdio: 'inherit' }); + } + } + } + + run(process.argv[2]); +} diff --git a/scripts/update-sdk-versions.mjs b/scripts/update-sdk-versions.mjs index 8c99e06f..6d7aa13c 100644 --- a/scripts/update-sdk-versions.mjs +++ b/scripts/update-sdk-versions.mjs @@ -6,32 +6,34 @@ import { fileURLToPath } from 'url'; const __dirname = fileURLToPath(new URL('.', import.meta.url)); -const latest = await latestVersion('@sentry/core'); -const packageJsonPath = join(__dirname, '..', 'package.json'); -const packageJson = JSON.parse(readFileSync(packageJsonPath, { encoding: 'utf8' })); -const current = packageJson.dependencies['@sentry/core']; +export default async function () { + const latest = await latestVersion('@sentry/core'); + const packageJsonPath = join(__dirname, '..', 'package.json'); + const packageJson = JSON.parse(readFileSync(packageJsonPath, { encoding: 'utf8' })); + const current = packageJson.dependencies['@sentry/core']; -if (current !== latest) { - console.log(`Updating Sentry deps from ${current} to ${latest}`); + if (current !== latest) { + console.log(`Updating Sentry deps from ${current} to ${latest}`); - const re = /^@sentry(-internal)?\//; + const re = /^@sentry(-internal)?\//; - for (const dep of Object.keys(packageJson.dependencies)) { - if (dep.match(re)) { - packageJson.dependencies[dep] = latest; + for (const dep of Object.keys(packageJson.dependencies)) { + if (dep.match(re)) { + packageJson.dependencies[dep] = latest; + } } - } - for (const dep of Object.keys(packageJson.devDependencies)) { - if (dep.match(re)) { - packageJson.devDependencies[dep] = latest; + for (const dep of Object.keys(packageJson.devDependencies)) { + if (dep.match(re)) { + packageJson.devDependencies[dep] = latest; + } } - } - writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); + writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); - // Update yarn.lock - spawnSync('yarn', ['install'], { stdio: 'inherit' }); - // Update parameter that has the version in it - spawnSync('yarn', ['build'], { stdio: 'inherit' }); + // Update lock file + spawnSync('npm', ['install'], { stdio: 'inherit' }); + // Update parameter that has the version in it + spawnSync('npm', ['run', 'build'], { stdio: 'inherit' }); + } } diff --git a/scripts/update-version.js b/scripts/update-version.js deleted file mode 100644 index 3a8a8921..00000000 --- a/scripts/update-version.js +++ /dev/null @@ -1,16 +0,0 @@ -const { join } = require('path'); -const { readFileSync, writeFileSync } = require('fs'); - -const packageJson = require('../package.json'); - -// SDK_VERSION to 'src/main/version.ts' -const versionPath = join(__dirname, '../src/main/version.ts'); -writeFileSync(versionPath, `export const SDK_VERSION = '${packageJson.version}';\n`); - -// Write @sentry/core version into options variable name so TypeScript error includes useful hint -const coreVersion = packageJson.dependencies['@sentry/core']; -const coreVersionVar = coreVersion.replace(/\./g, '_'); -const rendererSdkPath = join(__dirname, '../src/renderer/sdk.ts'); -let rendererSdk = readFileSync(rendererSdkPath, { encoding: 'utf8' }); -rendererSdk = rendererSdk.replace(/version_v\d+_\d+_\d+[a-z_0-9]*/, `version_v${coreVersionVar.replace(/-/, '_')}`); -writeFileSync(rendererSdkPath, rendererSdk); diff --git a/scripts/update-version.mjs b/scripts/update-version.mjs new file mode 100644 index 00000000..4aa44d6e --- /dev/null +++ b/scripts/update-version.mjs @@ -0,0 +1,21 @@ +import { join } from 'path'; +import { readFileSync, writeFileSync } from 'fs'; +import { fileURLToPath } from 'url'; + +const __dirname = fileURLToPath(new URL('.', import.meta.url)); + +export default function () { + const packageJson = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'))); + + // SDK_VERSION to 'src/main/version.ts' + const versionPath = join(__dirname, '../src/main/version.ts'); + writeFileSync(versionPath, `export const SDK_VERSION = '${packageJson.version}';\n`); + + // Write @sentry/core version into options variable name so TypeScript error includes useful hint + const coreVersion = packageJson.dependencies['@sentry/core']; + const coreVersionVar = coreVersion.replace(/[\.-]/g, '_'); + const rendererSdkPath = join(__dirname, '../src/renderer/sdk.ts'); + let rendererSdk = readFileSync(rendererSdkPath, { encoding: 'utf8' }); + rendererSdk = rendererSdk.replace(/version_v\d+_\d+_\d+[a-z_0-9]*/, `version_v${coreVersionVar}`); + writeFileSync(rendererSdkPath, rendererSdk); +} diff --git a/test/e2e/recipe/index.ts b/test/e2e/recipe/index.ts index fa11c12d..38cf4804 100644 --- a/test/e2e/recipe/index.ts +++ b/test/e2e/recipe/index.ts @@ -187,6 +187,11 @@ export class RecipeRunner { writeFileSync(path, content); } + // Yarn v4 requires an empty yarn.lock file otherwise it complains that this is not part of the parent workspace + if (!this._recipe.files['yarn.lock']) { + writeFileSync(join(appPath, 'yarn.lock'), ''); + } + if (this._recipe.metadata.command) { log(`Running command '${this._recipe.metadata.command}'`);