#!/usr/bin/env node /** * Docker Build and Push Script * * Builds Docker images and pushes them to the local registry. * Tags images based on git state: * - Tagged commit: versioned tags + latest * - Untagged commit: .dev suffix + commit hash */ const { execSync, spawn } = require('child_process'); const fs = require('fs'); const path = require('path'); // Configuration const REGISTRY = 'dhg.lol:5000'; const IMAGE_NAME = 'euchre-camp'; const FULL_IMAGE_NAME = `${REGISTRY}/${IMAGE_NAME}`; // Parse command line arguments const args = process.argv.slice(2); const forceVersion = args[0]; // Optional: force a specific version // Get current version from package.json function getCurrentVersion() { const packageJsonPath = path.join(__dirname, '..', 'package.json'); const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); return packageJson.version; } // Get git commit hash function getGitCommitHash(short = true) { const flag = short ? '--short' : ''; return execSync(`git rev-parse ${flag} HEAD`, { encoding: 'utf8' }).trim(); } // Get git tag (if any) function getGitTag() { try { const tag = execSync('git describe --tags --exact-match 2>/dev/null', { encoding: 'utf8' }).trim(); return tag; } catch (error) { return null; } } // Check if working directory is clean function isWorkingDirectoryClean() { try { const status = execSync('git status --porcelain', { encoding: 'utf8' }).trim(); return status === ''; } catch (error) { return false; } } // Build Docker image async function buildDockerImage(tags, gitCommit) { console.log(`🔨 Building Docker image...\n`); const buildArgs = [ 'build', '--build-arg', `GIT_COMMIT=${gitCommit}`, '-t', `${FULL_IMAGE_NAME}:${tags[0]}`, // Primary tag ]; // Add additional tags tags.forEach(tag => { buildArgs.push('-t', `${FULL_IMAGE_NAME}:${tag}`); }); buildArgs.push('.'); console.log(`Build command: docker ${buildArgs.join(' ')}\n`); return new Promise((resolve, reject) => { const docker = spawn('docker', buildArgs, { cwd: path.join(__dirname, '..'), stdio: 'inherit' }); docker.on('close', (code) => { if (code === 0) { console.log('✅ Docker image built successfully\n'); resolve(); } else { reject(new Error(`Docker build failed with code ${code}`)); } }); }); } // Push Docker image async function pushDockerImage(tags) { console.log(`🚀 Pushing Docker images to ${REGISTRY}...\n`); for (const tag of tags) { const imageName = `${FULL_IMAGE_NAME}:${tag}`; console.log(`Pushing ${imageName}...`); try { execSync(`docker push ${imageName}`, { stdio: 'inherit' }); console.log(`✅ Pushed ${imageName}\n`); } catch (error) { console.error(`❌ Failed to push ${imageName}:`, error.message); throw error; } } console.log('✅ All images pushed successfully\n'); } // Main function async function main() { console.log('🐳 Docker Build & Push Tool\n'); console.log(`Registry: ${REGISTRY}`); console.log(`Image: ${IMAGE_NAME}\n`); // Check if working directory is clean if (!isWorkingDirectoryClean()) { console.log('⚠️ Warning: Working directory is not clean'); console.log(' Proceeding anyway...\n'); } // Determine image tags const gitCommit = getGitCommitHash(); const gitTag = getGitTag(); const version = forceVersion || getCurrentVersion(); let tags = []; if (gitTag) { // Tagged commit - use version and 'latest' const tagWithoutV = gitTag.startsWith('v') ? gitTag.slice(1) : gitTag; if (tagWithoutV !== version) { console.log(`⚠️ Warning: Git tag (${gitTag}) doesn't match package.json version (${version})`); console.log(' Using package.json version for Docker tags\n'); } tags = [ version, // e.g., 0.1.0 'latest', // Latest stable ]; } else { // Untagged commit - use version with .dev suffix and commit hash tags = [ `${version}.dev`, // e.g., 0.1.0.dev `${version}-sha-${gitCommit}`, // e.g., 0.1.0-sha-abc123 ]; } console.log(`Git commit: ${gitCommit}`); console.log(`Git tag: ${gitTag || '(none)'}`); console.log(`Package version: ${version}`); console.log(`Docker tags: ${tags.join(', ')}\n`); // Build the image await buildDockerImage(tags, gitCommit); // Push the images await pushDockerImage(tags); console.log('🎉 Docker build and push complete!\n'); console.log('Images available at:'); tags.forEach(tag => { console.log(` - ${FULL_IMAGE_NAME}:${tag}`); }); } // Run main function main().catch(error => { console.error('❌ Error:', error.message); process.exit(1); });