scripts/utils/desktop_jobs.mjs (131 lines of code) (raw):

import path from 'node:path'; import fs from 'node:fs'; import { copyFile } from 'node:fs/promises'; import { ENVIRONMENTS } from '../constants.mjs'; import { root, run } from './run_utils.mjs'; import { createDesktopPackageJson } from './packages.mjs'; import { prepareWebviews, generateAssets, writePackageJson, commonJobs, copyStaticProjectFiles, } from './common_jobs.mjs'; const desktopWebviews = { vue3: ['issuable'], vue2: ['gitlab_duo_chat', 'security_finding'], }; export async function copyPendingJobAssets() { return copyFile( path.join(root, 'webviews/pendingjob.html'), path.join(root, `dist-desktop/webviews/pendingjob.html`), ); } export async function compileSource() { await run('tsc', ['-p', root]); } export async function buildExtension(args = [], signal) { await run( 'esbuild', [ path.join(root, 'src/desktop/extension.js'), '--bundle', '--outfile=dist-desktop/extension.js', '--external:vscode', '--platform=node', '--target=node18.17', '--sourcemap', '--loader:.html=text', ...args, ], { cancelSignal: signal }, ); } export async function checkAndBuildExtension(args = []) { await compileSource(); await buildExtension(args); } /** * Copy a directory using native OS utils * (not using NodeJS `fs` for performance reasons when copying large node_modules dirs) */ async function copyDirectory(sourcePath, destPath) { if (process.platform === 'win32') { // robocopy copies the contents of source into dest (does NOT create an additional subdirectory named after source) // So ensure we handle that by making a more specific destPath const sourceDir = path.basename(sourcePath); const fullDestPath = path.join(destPath, sourceDir); try { const reduceOutputVerbosityFlags = ['/NFL', '/NDL', '/NJH', '/NJS', '/nc', '/ns', '/np']; const copySubdirectoriesRecursivelyFlag = '/E'; await run('robocopy', [ sourcePath, fullDestPath, copySubdirectoriesRecursivelyFlag, ...reduceOutputVerbosityFlags, ]); } catch (error) { // robocopy exits with: // 0 - no files copied (no change/no files) // 1 - files copied successfully // 2+ - some errors occurred if (error.exitCode === 1 || error.code === 1) { console.log( 'robocopy exited with code 1. This is not an error, everything copied correctly.', ); return; } throw error; } } else { await run('cp', ['-R', sourcePath, destPath]); } } export async function copyNodeModules() { await copyDirectory(path.join(root, 'node_modules'), path.join(root, 'dist-desktop')); } export async function copyWalkthroughs() { await copyDirectory(path.join(root, 'walkthroughs'), path.join(root, 'dist-desktop')); } export function watchWebviews(signal) { const targets = Object.keys(desktopWebviews); targets.forEach(async target => { desktopWebviews[target].forEach(webview => { const dirpath = path.join(root, `webviews/${target}/dist/${webview}`); if (!fs.existsSync(dirpath)) fs.mkdirSync(dirpath, { recursive: true }); fs.symlinkSync(dirpath, path.join(root, `dist-desktop/webviews/${webview}`)); }); await run('npm', ['run', '--prefix', path.join(root, `webviews/${target}`), 'watch'], { cancelSignal: signal, }); }); } export async function buildDesktop() { const packageJson = createDesktopPackageJson(); await commonJobs(ENVIRONMENTS.DESKTOP); await Promise.all([ prepareWebviews(desktopWebviews, ENVIRONMENTS.DESKTOP), copyPendingJobAssets(), copyStaticProjectFiles(ENVIRONMENTS.DESKTOP), copyWalkthroughs(), checkAndBuildExtension(['--minify']), generateAssets(packageJson, ENVIRONMENTS.DESKTOP), ]); // we need to wait for `tsc` to compile so we can replace package.json await writePackageJson(packageJson, ENVIRONMENTS.DESKTOP); } export async function watchDesktop(signal) { const packageJson = createDesktopPackageJson(); await compileSource(); await writePackageJson(packageJson, ENVIRONMENTS.DESKTOP); copyStaticProjectFiles(ENVIRONMENTS.DESKTOP); copyWalkthroughs(); await buildExtension(['--watch'], signal); } export async function buildPackage(options, isPreReleaseBuild) { const args = ['--no-dependencies']; if (isPreReleaseBuild) { args.push('--pre-release'); } await run('vsce', ['package', ...args], options); }