Refactor build configs and improve CI/CD checks
This commit makes the build process more robust, simplifies configurations and reduce the risk of incomplete or erroneous deployments. - Centralize output directory definitions by introducing `dist-dirs.json`. - Add `verify-build-artifacts` utility to ensure correct build outputs and `print-dist-dir` to determine distribution directory. - Add steps in CI/CD pipeline to verify build artifacts. - Migrate Electron Builder config from YAML to CJS for capability to read JSON. - Fix `release-site.yaml` failing due to pointing to wrong distribution directory, change it to use `print-dist-dir`. - Improve `check-desktop-runtime-errors` to verify build artifacts for more reliable builds. Ensure tests fail and succeed reliably. - Update `.gitignore` and configure ESLint to use it to define and ignore build artifact directories from one place, remove `.eslintignore` that does not add anything after this change. - Keep `"main"` field in `package.json` as `electron-vite` depends on it (alex8088/electron-vite#270). - Improve documentation
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
dist/
|
||||
dist_electron/
|
||||
15
.github/workflows/checks.build.yaml
vendored
15
.github/workflows/checks.build.yaml
vendored
@@ -29,8 +29,11 @@ jobs:
|
||||
name: Install dependencies
|
||||
run: npm ci
|
||||
-
|
||||
name: Build
|
||||
name: Build web
|
||||
run: npm run build -- --mode ${{ matrix.mode }}
|
||||
-
|
||||
name: Verify web build artifacts
|
||||
run: npm run check:verify-build-artifacts -- --web
|
||||
|
||||
build-desktop:
|
||||
strategy:
|
||||
@@ -54,11 +57,17 @@ jobs:
|
||||
name: Install dependencies
|
||||
run: npm ci
|
||||
-
|
||||
name: Prebuild
|
||||
name: Prebuild desktop
|
||||
run: npm run electron:prebuild -- --mode ${{ matrix.mode }}
|
||||
-
|
||||
name: Build
|
||||
name: Verify unbundled desktop build artifacts
|
||||
run: npm run check:verify-build-artifacts -- --electron-unbundled
|
||||
-
|
||||
name: Build (bundle and package) desktop application
|
||||
run: npm run electron:build -- --publish never
|
||||
-
|
||||
name: Verify bundled desktop build artifacts
|
||||
run: npm run check:verify-build-artifacts -- --electron-bundled
|
||||
|
||||
create-icons:
|
||||
strategy:
|
||||
|
||||
12
.github/workflows/release.site.yaml
vendored
12
.github/workflows/release.site.yaml
vendored
@@ -94,11 +94,21 @@ jobs:
|
||||
name: "App: Build"
|
||||
run: npm run build
|
||||
working-directory: app
|
||||
-
|
||||
name: "App: Verify web build artifacts"
|
||||
run: npm run check:verify-build-artifacts -- --web
|
||||
working-directory: app
|
||||
-
|
||||
name: "App: Deploy to S3"
|
||||
shell: bash
|
||||
run: >-
|
||||
declare web_output_dir
|
||||
if ! web_output_dir=$(cd app && node scripts/print-dist-dir.js --web); then
|
||||
echo 'Error: Could not determine distribution directory.'
|
||||
exit 1
|
||||
fi
|
||||
bash "aws/scripts/deploy/deploy-to-s3.sh" \
|
||||
--folder app/dist \
|
||||
--folder "${web_output_dir}" \
|
||||
--web-stack-name privacysexy-web-stack --web-stack-s3-name-output-name S3BucketName \
|
||||
--storage-class ONEZONE_IA \
|
||||
--role-arn ${{secrets.AWS_S3_SITE_DEPLOYMENT_ROLE_ARN}} \
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,7 +1,5 @@
|
||||
node_modules
|
||||
dist/
|
||||
/dist-*/
|
||||
.vs
|
||||
.vscode/**/*
|
||||
!.vscode/extensions.json
|
||||
#Electron-builder output
|
||||
/dist_electron
|
||||
!.vscode/extensions.json
|
||||
5
dist-dirs.json
Normal file
5
dist-dirs.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"electronUnbundled": "dist-electron-unbundled",
|
||||
"electronBundled": "dist-electron-bundled",
|
||||
"web": "dist-web"
|
||||
}
|
||||
@@ -5,7 +5,9 @@ Before your commit, a good practice is to:
|
||||
1. [Run unit tests](#testing)
|
||||
2. [Lint your code](#linting)
|
||||
|
||||
You could run other types of tests as well, but they may take longer time and overkill for your changes. Automated actions executes the tests for a pull request or change in the main branch. See [ci-cd.md](./ci-cd.md) for more information.
|
||||
You could run other types of tests as well, but they may take longer time and overkill for your changes.
|
||||
Automated actions are set up to execute these tests as necessary.
|
||||
See [ci-cd.md](./ci-cd.md) for more information.
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -65,13 +67,26 @@ You could run other types of tests as well, but they may take longer time and ov
|
||||
- Build desktop application: `npm run electron:build`
|
||||
- (Re)create icons (see [documentation](../img/README.md)): `npm run create-icons`
|
||||
|
||||
### Utility Scripts
|
||||
### Scripts
|
||||
|
||||
- Run fresh NPM install: [`./scripts/fresh-npm-install.sh`](../scripts/fresh-npm-install.sh)
|
||||
📖 For detailed options and behavior for any of the following scripts, please refer to the script file itself.
|
||||
|
||||
#### Utility scripts
|
||||
|
||||
- [**`./scripts/fresh-npm-install.sh`**](../scripts/fresh-npm-install.sh):
|
||||
- Run fresh NPM install.
|
||||
- This script provides a clean NPM install, removing existing node modules and optionally the package-lock.json (when run with -n), then installs dependencies and runs unit tests.
|
||||
- Configure VSCode: [`./scripts/configure-vscode.sh`](../scripts/configure-vscode.sh)
|
||||
- [**`./scripts/configure-vscode.sh`**](../scripts/configure-vscode.sh):
|
||||
- This script checks and sets the necessary configurations for VSCode in `settings.json` file.
|
||||
|
||||
#### Automation scripts
|
||||
|
||||
- [**`node scripts/print-dist-dir.js [-- <options>]`**](../scripts/print-dist-dir.js):
|
||||
- Determines the absolute path of a distribution directory based on CLI arguments and outputs its absolute path.
|
||||
- Primarily used by automation scripts.
|
||||
- [**`npm run check:verify-build-artifacts [-- <options>]`**](../scripts/verify-build-artifacts.js):
|
||||
- Verifies the existence and content of build artifacts. Useful for ensuring that the build process is generating the expected output.
|
||||
|
||||
## Recommended extensions
|
||||
|
||||
You should use EditorConfig to follow project style.
|
||||
|
||||
43
electron-builder.cjs
Normal file
43
electron-builder.cjs
Normal file
@@ -0,0 +1,43 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
|
||||
const { join } = require('path');
|
||||
const { electronBundled, electronUnbundled } = require('./dist-dirs.json');
|
||||
|
||||
module.exports = {
|
||||
// Common options
|
||||
publish: {
|
||||
provider: 'github',
|
||||
vPrefixedTagName: false, // default: true
|
||||
releaseType: 'release', // default: draft
|
||||
},
|
||||
directories: {
|
||||
output: electronBundled,
|
||||
},
|
||||
extraMetadata: {
|
||||
main: join(electronUnbundled, 'main/index.cjs'), // do not `path.resolve`, it expects a relative path
|
||||
},
|
||||
|
||||
// Windows
|
||||
win: {
|
||||
target: 'nsis',
|
||||
},
|
||||
nsis: {
|
||||
artifactName: '${name}-Setup-${version}.${ext}',
|
||||
},
|
||||
|
||||
// Linux
|
||||
linux: {
|
||||
target: 'AppImage',
|
||||
},
|
||||
appImage: {
|
||||
artifactName: '${name}-${version}.${ext}',
|
||||
},
|
||||
|
||||
// macOS
|
||||
mac: {
|
||||
target: 'dmg',
|
||||
},
|
||||
dmg: {
|
||||
artifactName: '${name}-${version}.${ext}',
|
||||
},
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
# -------
|
||||
# Windows
|
||||
# -------
|
||||
win:
|
||||
target: nsis
|
||||
nsis:
|
||||
artifactName: ${name}-Setup-${version}.${ext}
|
||||
|
||||
# -----
|
||||
# Linux
|
||||
# -----
|
||||
linux:
|
||||
target: AppImage
|
||||
appImage:
|
||||
artifactName: ${name}-${version}.${ext}
|
||||
|
||||
# -----
|
||||
# macOS
|
||||
# -----
|
||||
mac:
|
||||
target: dmg
|
||||
dmg:
|
||||
artifactName: ${name}-${version}.${ext}
|
||||
|
||||
# ----------------
|
||||
# Publish options
|
||||
# ----------------
|
||||
publish:
|
||||
provider: 'github'
|
||||
vPrefixedTagName: false # default: true
|
||||
releaseType: release # default: draft
|
||||
@@ -3,11 +3,12 @@ import { mergeConfig, UserConfig } from 'vite';
|
||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
|
||||
import { getAliasesFromTsConfig, getClientEnvironmentVariables } from './vite-config-helper';
|
||||
import { createVueConfig } from './vite.config';
|
||||
import distDirs from './dist-dirs.json' assert { type: 'json' };
|
||||
|
||||
const MAIN_ENTRY_FILE = resolvePathFromProjectRoot('src/presentation/electron/main/index.ts');
|
||||
const PRELOAD_ENTRY_FILE = resolvePathFromProjectRoot('src/presentation/electron/preload/index.ts');
|
||||
const WEB_INDEX_HTML_PATH = resolvePathFromProjectRoot('src/presentation/index.html');
|
||||
const DIST_DIR = resolvePathFromProjectRoot('dist_electron/');
|
||||
const DIST_DIR = resolvePathFromProjectRoot(distDirs.electronUnbundled);
|
||||
|
||||
export default defineConfig({
|
||||
main: getSharedElectronConfig({
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"description": "Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy 🍑🍆",
|
||||
"author": "undergroundwires",
|
||||
"type": "module",
|
||||
"main": "./dist-electron-unbundled/main/index.cjs",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
@@ -18,11 +19,12 @@
|
||||
"icons:build": "node scripts/logo-update.js",
|
||||
"check:desktop": "vitest run --dir tests/checks/desktop-runtime-errors --environment node",
|
||||
"check:external-urls": "vitest run --dir tests/checks/external-urls --environment node",
|
||||
"check:verify-build-artifacts": "node scripts/verify-build-artifacts",
|
||||
"electron:dev": "electron-vite dev",
|
||||
"electron:preview": "electron-vite preview",
|
||||
"electron:prebuild": "electron-vite build",
|
||||
"electron:build": "electron-builder",
|
||||
"lint:eslint": "eslint .",
|
||||
"lint:eslint": "eslint . --ignore-path .gitignore",
|
||||
"lint:md": "markdownlint **/*.md --ignore node_modules",
|
||||
"lint:md:consistency": "remark . --frail --use remark-preset-lint-consistent",
|
||||
"lint:md:relative-urls": "remark . --frail --use remark-validate-links",
|
||||
@@ -30,7 +32,6 @@
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"postuninstall": "electron-builder install-app-deps"
|
||||
},
|
||||
"main": "./dist_electron/main/index.cjs",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.4.0",
|
||||
|
||||
58
scripts/print-dist-dir.js
Normal file
58
scripts/print-dist-dir.js
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Description:
|
||||
* This script determines the absolute path of a distribution directory based on CLI arguments
|
||||
* and outputs its absolute path. It is designed to be run programmatically by other scripts.
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/print-dist-dir.js [options]
|
||||
*
|
||||
* Options:
|
||||
* --electron-unbundled Path for the unbundled Electron application
|
||||
* --electron-bundled Path for the bundled Electron application
|
||||
* --web Path for the web application
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { readFile } from 'fs/promises';
|
||||
|
||||
const DIST_DIRS_JSON_FILE_PATH = resolve(process.cwd(), 'dist-dirs.json'); // cannot statically import because ESLint does not support it https://github.com/eslint/eslint/discussions/15305
|
||||
const CLI_ARGUMENTS = process.argv.slice(2);
|
||||
|
||||
async function main() {
|
||||
const distDirs = await readDistDirsJsonFile(DIST_DIRS_JSON_FILE_PATH);
|
||||
const relativeDistDir = determineRelativeDistDir(distDirs, CLI_ARGUMENTS);
|
||||
const absoluteDistDir = resolve(process.cwd(), relativeDistDir);
|
||||
console.log(absoluteDistDir);
|
||||
}
|
||||
|
||||
function mapCliFlagsToDistDirs(distDirs) {
|
||||
return {
|
||||
'--electron-unbundled': distDirs.electronUnbundled,
|
||||
'--electron-bundled': distDirs.electronBundled,
|
||||
'--web': distDirs.web,
|
||||
};
|
||||
}
|
||||
|
||||
function determineRelativeDistDir(distDirsJsonObject, cliArguments) {
|
||||
const cliFlagDistDirMap = mapCliFlagsToDistDirs(distDirsJsonObject);
|
||||
const availableCliFlags = Object.keys(cliFlagDistDirMap);
|
||||
const requestedCliFlags = cliArguments.filter((arg) => {
|
||||
return availableCliFlags.includes(arg);
|
||||
});
|
||||
if (!requestedCliFlags.length) {
|
||||
throw new Error(`No distribution directory was requested. Please use one of these flags: ${availableCliFlags.join(', ')}`);
|
||||
}
|
||||
if (requestedCliFlags.length > 1) {
|
||||
throw new Error(`Multiple distribution directories were requested, but this script only supports one: ${requestedCliFlags.join(', ')}`);
|
||||
}
|
||||
const selectedCliFlag = requestedCliFlags[0];
|
||||
return cliFlagDistDirMap[selectedCliFlag];
|
||||
}
|
||||
|
||||
async function readDistDirsJsonFile(absoluteConfigJsonFilePath) {
|
||||
const fileContentAsText = await readFile(absoluteConfigJsonFilePath, 'utf8');
|
||||
const parsedJsonData = JSON.parse(fileContentAsText);
|
||||
return parsedJsonData;
|
||||
}
|
||||
|
||||
await main();
|
||||
133
scripts/verify-build-artifacts.js
Normal file
133
scripts/verify-build-artifacts.js
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Description:
|
||||
* This script verifies the existence and content of build artifacts based on the
|
||||
* provided CLI flags. It exists with exit code `0` if all verifications pass, otherwise
|
||||
* with exit code `1`.
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/verify-build-artifacts.js [options]
|
||||
*
|
||||
* Options:
|
||||
* --electron-unbundled Verify artifacts for the unbundled Electron application.
|
||||
* --electron-bundled Verify artifacts for the bundled Electron application.
|
||||
* --web Verify artifacts for the web application.
|
||||
*/
|
||||
|
||||
import { access, readdir } from 'fs/promises';
|
||||
import { exec } from 'child_process';
|
||||
import { resolve } from 'path';
|
||||
|
||||
const PROCESS_ARGUMENTS = process.argv.slice(2);
|
||||
const PRINT_DIST_DIR_SCRIPT_BASE_COMMAND = 'node scripts/print-dist-dir';
|
||||
|
||||
async function main() {
|
||||
const buildConfigs = getBuildVerificationConfigs();
|
||||
if (!anyCommandsFound(Object.keys(buildConfigs))) {
|
||||
die(`No valid command found in process arguments. Expected one of: ${Object.keys(buildConfigs).join(', ')}`);
|
||||
}
|
||||
/* eslint-disable no-await-in-loop */
|
||||
for (const [command, config] of Object.entries(buildConfigs)) {
|
||||
if (PROCESS_ARGUMENTS.includes(command)) {
|
||||
const distDir = await executePrintDistDirScript(config.printDistDirScriptArgument);
|
||||
await verifyDirectoryExists(distDir);
|
||||
await verifyNonEmptyDirectory(distDir);
|
||||
await verifyFilesExist(distDir, config.filePatterns);
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-await-in-loop */
|
||||
console.log('✅ Build completed successfully and all expected artifacts are in place.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
function getBuildVerificationConfigs() {
|
||||
return {
|
||||
'--electron-unbundled': {
|
||||
printDistDirScriptArgument: '--electron-unbundled',
|
||||
filePatterns: [
|
||||
/main[/\\]index\.cjs/,
|
||||
/preload[/\\]index\.cjs/,
|
||||
/renderer[/\\]index\.htm(l)?/,
|
||||
],
|
||||
},
|
||||
'--electron-bundled': {
|
||||
printDistDirScriptArgument: '--electron-bundled',
|
||||
filePatterns: [
|
||||
/latest.*\.yml/, // generates latest.yml for auto-updates
|
||||
/.*-\d+\.\d+\.\d+\..*/, // a file with extension and semantic version (packaged application)
|
||||
],
|
||||
},
|
||||
'--web': {
|
||||
printDistDirScriptArgument: '--web',
|
||||
filePatterns: [
|
||||
/index\.htm(l)?/,
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function anyCommandsFound(commands) {
|
||||
return PROCESS_ARGUMENTS.some((arg) => commands.includes(arg));
|
||||
}
|
||||
|
||||
async function verifyDirectoryExists(directoryPath) {
|
||||
try {
|
||||
await access(directoryPath);
|
||||
} catch (error) {
|
||||
die(`Directory does not exist at \`${directoryPath}\`:\n\t${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyNonEmptyDirectory(directoryPath) {
|
||||
const files = await readdir(directoryPath);
|
||||
if (files.length === 0) {
|
||||
die(`Directory is empty at \`${directoryPath}\``);
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyFilesExist(directoryPath, filePatterns) {
|
||||
const files = await listAllFilesRecursively(directoryPath);
|
||||
for (const pattern of filePatterns) {
|
||||
const match = files.some((file) => pattern.test(file));
|
||||
if (!match) {
|
||||
die(
|
||||
`No file matches the pattern ${pattern.source} in directory \`${directoryPath}\``,
|
||||
`\nFiles in directory:\n${files.map((file) => `\t- ${file}`).join('\n')}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function listAllFilesRecursively(directoryPath) {
|
||||
const dir = await readdir(directoryPath, { withFileTypes: true });
|
||||
const files = await Promise.all(dir.map(async (dirent) => {
|
||||
const absolutePath = resolve(directoryPath, dirent.name);
|
||||
if (dirent.isDirectory()) {
|
||||
return listAllFilesRecursively(absolutePath);
|
||||
}
|
||||
return absolutePath;
|
||||
}));
|
||||
return files.flat();
|
||||
}
|
||||
|
||||
async function executePrintDistDirScript(flag) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const commandToRun = `${PRINT_DIST_DIR_SCRIPT_BASE_COMMAND} ${flag}`;
|
||||
|
||||
exec(commandToRun, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(new Error(`Execution failed with error: ${error}`));
|
||||
} else if (stderr) {
|
||||
reject(new Error(`Execution failed with stderr: ${stderr}`));
|
||||
} else {
|
||||
resolve(stdout.trim());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function die(...message) {
|
||||
console.error(...message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await main();
|
||||
@@ -1,7 +1,13 @@
|
||||
import { join } from 'path';
|
||||
import distDirs from '@/../dist-dirs.json' assert { type: 'json' };
|
||||
|
||||
export const DESKTOP_BUILD_COMMAND = 'npm run electron:prebuild && npm run electron:build -- --publish never';
|
||||
export const DESKTOP_BUILD_COMMAND = [
|
||||
'npm run electron:prebuild',
|
||||
'npm run check:verify-build-artifacts -- --electron-unbundled',
|
||||
'npm run electron:build -- --publish never',
|
||||
'npm run check:verify-build-artifacts -- --electron-bundled',
|
||||
].join(' && ');
|
||||
export const PROJECT_DIR = process.cwd();
|
||||
export const DESKTOP_DIST_PATH = join(PROJECT_DIR, 'dist');
|
||||
export const DESKTOP_DIST_PATH = join(PROJECT_DIR, distDirs.electronBundled);
|
||||
export const APP_EXECUTION_DURATION_IN_SECONDS = 60; // Long enough for CI runners
|
||||
export const SCREENSHOT_PATH = join(PROJECT_DIR, 'screenshot.png');
|
||||
|
||||
@@ -60,7 +60,11 @@ export async function npmBuild(
|
||||
cwd: projectDir,
|
||||
});
|
||||
if (error) {
|
||||
log(error, LogLevel.Warn); // Cannot disable Vue CLI errors, stderr contains false-positives.
|
||||
die(error);
|
||||
}
|
||||
|
||||
if (await isDirMissingOrEmpty(distDir)) {
|
||||
die(`The desktop application build process did not produce the expected artifacts. The output directory "${distDir}" is empty or missing.`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,67 @@
|
||||
import { test } from 'vitest';
|
||||
import {
|
||||
describe, it, beforeAll, afterAll,
|
||||
} from 'vitest';
|
||||
import { main } from './check-desktop-runtime-errors/main';
|
||||
import { COMMAND_LINE_FLAGS, CommandLineFlag } from './check-desktop-runtime-errors/cli-args';
|
||||
|
||||
test('should have no desktop runtime errors', async () => {
|
||||
// arrange
|
||||
setCommandLineFlagsFromEnvironmentVariables();
|
||||
let exitCode: number;
|
||||
global.process.exit = (code?: number): never => {
|
||||
exitCode = code;
|
||||
return undefined as never;
|
||||
};
|
||||
// act
|
||||
await main();
|
||||
// assert
|
||||
expect(exitCode).to.equal(0);
|
||||
}, {
|
||||
timeout: 60 /* minutes */ * 10000,
|
||||
describe('desktop runtime error checks', () => {
|
||||
const { waitForExitCode } = useInterceptedProcessExitOrCompletion(beforeAll, afterAll);
|
||||
it('should successfully execute the main function and exit with a zero status code', async () => {
|
||||
// arrange
|
||||
setCommandLineFlagsFromEnvironmentVariables();
|
||||
// act
|
||||
const exitCode = await waitForExitCode(
|
||||
() => main(),
|
||||
);
|
||||
// assert
|
||||
expect(exitCode).to.equal(0);
|
||||
}, {
|
||||
timeout: 60 /* minutes */ * 60000,
|
||||
});
|
||||
});
|
||||
|
||||
function useInterceptedProcessExitOrCompletion(
|
||||
beforeTest: (callback: () => void) => void,
|
||||
afterTest: (callback: () => void) => void,
|
||||
) {
|
||||
const originalFunction = global.process.exit;
|
||||
let isExitCodeReceived = false;
|
||||
let exitCodeResolver: (value: number | undefined) => void;
|
||||
const waitForExitCode = (runner: () => Promise<void>) => new Promise<number | undefined>(
|
||||
(resolve, reject) => {
|
||||
exitCodeResolver = resolve;
|
||||
runner()
|
||||
.catch((error) => {
|
||||
if (isExitCodeReceived) {
|
||||
return;
|
||||
}
|
||||
console.error('Process did not call `process.exit` but threw an error:', error);
|
||||
reject(error);
|
||||
})
|
||||
.then(() => {
|
||||
if (isExitCodeReceived) {
|
||||
return;
|
||||
}
|
||||
console.log('Process completed without calling `process.exit`. Treating as `0` exit code.');
|
||||
exitCodeResolver(0);
|
||||
});
|
||||
},
|
||||
);
|
||||
beforeTest(() => {
|
||||
global.process.exit = (code?: number): never => {
|
||||
exitCodeResolver(code);
|
||||
isExitCodeReceived = true;
|
||||
return undefined as never;
|
||||
};
|
||||
});
|
||||
afterTest(() => {
|
||||
global.process.exit = originalFunction;
|
||||
});
|
||||
return {
|
||||
waitForExitCode,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Map environment variables to CLI arguments for compatibility with Vitest.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@ import { defineConfig, UserConfig } from 'vite';
|
||||
import legacy from '@vitejs/plugin-legacy';
|
||||
import vue from '@vitejs/plugin-vue2';
|
||||
import ViteYaml from '@modyfi/vite-plugin-yaml';
|
||||
import distDirs from './dist-dirs.json' assert { type: 'json' };
|
||||
import { getAliasesFromTsConfig, getClientEnvironmentVariables, getSelfDirectoryAbsolutePath } from './vite-config-helper';
|
||||
|
||||
const WEB_DIRECTORY = resolve(getSelfDirectoryAbsolutePath(), 'src/presentation');
|
||||
@@ -14,6 +15,9 @@ export function createVueConfig(options?: {
|
||||
}): UserConfig {
|
||||
return {
|
||||
root: WEB_DIRECTORY,
|
||||
build: {
|
||||
outDir: resolve(getSelfDirectoryAbsolutePath(), distDirs.web),
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
ViteYaml(),
|
||||
|
||||
Reference in New Issue
Block a user