Files
euchre_camp/scripts/build-and-push-docker.js
T
2026-03-31 19:16:15 -07:00

177 lines
4.7 KiB
JavaScript
Executable File

#!/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 = 'docker.notsosm.art';
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);
});