def deploy() { node('ubuntu') { try { stage('Deploy (Ubuntu)') { checkout scm nodejs(nodeJSInstallationName: 'Node23') { sh 'npm ci --include=dev' sh 'npm run build' // Deploy to Cloudflare Pages using wrangler // CLOUDFLARE_API_TOKEN should be set as a Jenkins credential/env variable sh 'npx wrangler pages deploy build' } } } finally { cleanWs() } } } def buildOnLabel(label, buildCommand) { return { node(label) { env.NODE_ENV = 'production' try { stage("Checkout (${label})") { checkout scm } stage("Setup Node.js (${label})") { nodejs(nodeJSInstallationName: 'Node23') { if (isUnix()) { sh 'node -v' sh 'npm -v' } else { bat 'node -v' bat 'npm -v' } } } stage("Install Dependencies (${label})") { nodejs(nodeJSInstallationName: 'Node23') { if (isUnix()) { sh 'npm ci --include=dev' } else { bat 'npm ci --include=dev' } } } stage("Build (${label})") { nodejs(nodeJSInstallationName: 'Node23') { if (isUnix()) { sh buildCommand sh 'ls -la build || echo "Build directory not found"' } else { bat buildCommand bat 'if not exist build echo "Build directory not found"' } } } stage("Verify Build (${label})") { if (isUnix()) { sh 'test -d build || (echo "Build directory does not exist" && exit 1)' } else { bat 'if not exist build (echo "Build directory does not exist" && exit 1)' } } } finally { cleanWs() } } } } try { parallel( 'Windows Build': buildOnLabel('windows', 'npm run build:electron'), 'MacOS Build': buildOnLabel('macos', 'npm run build:electron'), 'Ubuntu Deploy': { deploy() } ) echo 'All parallel stages completed successfully!' } catch (Exception e) { echo "Pipeline failed: ${e.message}" throw e }