#!/usr/bin/env node const { execSync } = require('child_process'); const fs = require('fs'); const { parseArgs } = require('util'); function execCommand(command, description) { try { console.log(`${description}...`); execSync(command, { stdio: 'inherit' }); } catch (error) { console.error(`Error: ${description} failed`); process.exit(1); } } function getContainerTool() { // Check for Docker first (primary tool) try { execSync('docker --version', { stdio: 'ignore' }); return 'docker'; } catch (error) { // Fall back to Apple's container command try { execSync('container --version', { stdio: 'ignore' }); return 'container'; } catch (error) { console.error('Error: No container tool found. Please install Docker or Apple Container Tools to build container images.'); process.exit(1); } } } function getVersion() { try { // Try to get version from git tag const gitTag = execSync('git tag --points-at HEAD', { encoding: 'utf8' }).trim(); if (gitTag) { return { version: gitTag.replace(/^v/, ''), isRelease: true }; } } catch (error) { // Git command failed, ignore } // Development build - use package.json version with -dev suffix const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); return { version: `${packageJson.version}-dev`, isRelease: false }; } function getHostArchitecture() { // Map Node.js architecture names to container architecture names const archMap = { 'arm64': 'arm64', 'arm': 'arm64', 'x64': 'amd64' }; return archMap[process.arch] || 'arm64'; } function showHelp() { const hostArch = getHostArchitecture(); console.log(`Build multi-architecture container images for JMESPath Playground Usage: build-image.js [OPTIONS] Options: --all-arch Build for both arm64 and amd64 (default: build for host architecture only) --arch Target architecture (arm64 or amd64). Can be specified multiple times. --help, -h Show this help message and exit Examples: build-image.js # Builds for ${hostArch} only (host architecture) build-image.js --all-arch # Builds for both arm64 and amd64 build-image.js --arch arm64 # Builds for arm64 only build-image.js --arch arm64 --arch amd64 # Explicitly specify both build-image.js -h # Show help`); } function main() { const { values } = parseArgs({ options: { help: { type: 'boolean', short: 'h', description: 'Show help' }, 'all-arch': { type: 'boolean', description: 'Build for both arm64 and amd64' }, arch: { type: 'string', multiple: true, description: 'Target architecture (arm64 or amd64)' } }, strict: true, allowPositionals: false }); if (values.help) { showHelp(); process.exit(0); } const containerTool = getContainerTool(); const { version, isRelease } = getVersion(); let architectures; if (values['all-arch']) { architectures = ['arm64', 'amd64']; } else if (values.arch && values.arch.length > 0) { architectures = values.arch; } else { architectures = [getHostArchitecture()]; } console.log(`Building ${isRelease ? 'release' : 'development'} version: ${version}`); console.log(`Target architectures: ${architectures.join(', ')}`); // Build container image const tags = isRelease ? [ `-t skoszewski/jmespath-playground:${version}`, `-t skoszewski/jmespath-playground:latest` ].join(' ') : [ `-t skoszewski/jmespath-playground:dev`, `-t skoszewski/jmespath-playground:latest` ].join(' '); const archFlags = architectures.map(arch => `--arch ${arch}`).join(' '); const buildCommand = `${containerTool} build ${archFlags} --build-arg VERSION="${version}" --build-arg IS_RELEASE="${isRelease}" ${tags} .`; execCommand(buildCommand, 'Building container image'); console.log('Container image build completed successfully!'); // Show usage instructions console.log(`\nUsage examples:`); console.log(` build-image.js # Builds for host architecture only`); console.log(` build-image.js --all-arch # Builds for both arm64 and amd64`); console.log(` build-image.js --arch arm64 # Builds for arm64 only`); console.log(` build-image.js --arch arm64 --arch amd64 # Explicitly specify both`); if (isRelease) { console.log(`\nTo run the container:`); console.log(` ${containerTool} run --arch arm64 --name jmespathpg -p 3000:3000 skoszewski/jmespath-playground:${version}`); if (containerTool === 'docker') { console.log(`\nTo push to Docker Hub:`); console.log(` docker push skoszewski/jmespath-playground:${version}`); console.log(` docker push skoszewski/jmespath-playground:latest`); } } else { console.log(`\nTo run the container:`); console.log(` ${containerTool} run --arch arm64 --name jmespathpg -p 3000:3000 skoszewski/jmespath-playground:dev`); } } if (require.main === module) { main(); }