From 4d6efe791bccde9a7e65ed447a0830c076a1ac8d Mon Sep 17 00:00:00 2001 From: Slawomir Koszewski Date: Wed, 21 Jan 2026 21:33:58 +0100 Subject: [PATCH] Version 1.1.2 --- package.json | 2 +- scripts/new-version.js | 256 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 230 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index faf03ec..d0488a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jmespath-playground", - "version": "1.1.1", + "version": "1.1.2", "description": "A React-based web application for testing JMESPath expressions against JSON data", "main": "index.js", "scripts": { diff --git a/scripts/new-version.js b/scripts/new-version.js index df80a8e..cf03374 100755 --- a/scripts/new-version.js +++ b/scripts/new-version.js @@ -4,37 +4,210 @@ const fs = require('fs'); const { execSync } = require('child_process'); function showUsage() { - console.log('Usage: node scripts/new-version.js '); + console.log('Usage: node scripts/new-version.js [--force]'); + console.log(' node scripts/new-version.js --check '); console.log(''); - console.log('Creates a new version by updating package.json, committing, and tagging.'); + console.log('Creates a new version by tagging the current commit.'); + console.log(''); + console.log('Options:'); + console.log(' --force Force version creation even with dirty repo or package.json mismatch'); + console.log(' --check Analyze repository status and report what would happen for specified version'); console.log(''); console.log('Example:'); console.log(' node scripts/new-version.js 1.2.0'); - console.log(' node scripts/new-version.js 2.0.0-beta.1'); + console.log(' node scripts/new-version.js 1.2.0 --force'); + console.log(' node scripts/new-version.js --check 1.3.0'); +} + +function performCheck(targetVersion) { + console.log('🔍 Repository Analysis Report'); + console.log('============================'); + + try { + // Read package.json + const packagePath = './package.json'; + const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8')); + const currentVersion = pkg.version; + + console.log(`📦 Package.json version: ${currentVersion}`); + + // Check repository status + let isRepoDirty = false; + let dirtyFiles = ''; + try { + const status = execSync('git status --porcelain', { encoding: 'utf8' }); + isRepoDirty = status.trim() !== ''; + dirtyFiles = status.trim(); + } catch (error) { + console.log('⚠️ Cannot determine git status'); + } + + if (isRepoDirty) { + console.log('🔄 Repository status: DIRTY'); + console.log(' Uncommitted changes:'); + dirtyFiles.split('\n').forEach(line => { + if (line.trim()) console.log(` ${line}`); + }); + } else { + console.log('✅ Repository status: CLEAN'); + } + + // Check current commit info + try { + const currentCommit = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim(); + const currentBranch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim(); + console.log(`🌟 Current commit: ${currentCommit.substring(0, 7)} (${currentBranch})`); + + // Check if current commit is tagged + const tagsOnHead = execSync('git tag --points-at HEAD', { encoding: 'utf8' }).trim(); + if (tagsOnHead) { + console.log(`🏷️ Current commit tags: ${tagsOnHead.split('\n').join(', ')}`); + } else { + console.log('🏷️ Current commit: No tags'); + } + } catch (error) { + console.log('⚠️ Cannot determine commit info'); + } + + // List recent tags + try { + const recentTags = execSync('git tag --sort=-version:refname | head -5', { encoding: 'utf8' }).trim(); + if (recentTags) { + console.log('📋 Recent tags:'); + recentTags.split('\n').forEach(tag => { + if (tag.trim()) console.log(` ${tag}`); + }); + } else { + console.log('📋 No tags found in repository'); + } + } catch (error) { + console.log('⚠️ Cannot list tags'); + } + + console.log(''); + + // Analysis for target version (if provided) + if (targetVersion) { + const tagName = `v${targetVersion}`; + console.log(`🎯 Analysis for version ${targetVersion}:`); + console.log('====================================='); + + // Check if target tag exists + try { + const existingTags = execSync('git tag -l', { encoding: 'utf8' }); + const tagExists = existingTags.split('\n').includes(tagName); + + if (tagExists) { + console.log(`❌ Tag '${tagName}' already exists - CANNOT CREATE`); + return; + } + console.log(`✅ Tag '${tagName}' available`); + } catch (error) { + console.log('⚠️ Cannot check tag availability'); + return; + } + + // Analyze what actions would be needed + const packageJsonMatches = currentVersion === targetVersion; + const needsPackageUpdate = !packageJsonMatches; + const needsCommit = isRepoDirty || needsPackageUpdate; + + console.log(`📝 Package.json: ${packageJsonMatches ? 'MATCHES' : `NEEDS UPDATE (${currentVersion} → ${targetVersion})`}`); + + if (needsCommit) { + console.log('⚡ Actions needed:'); + if (needsPackageUpdate) { + console.log(' • Update package.json'); + } + if (isRepoDirty) { + console.log(' • Stage uncommitted changes'); + } + console.log(' • Create commit'); + console.log(` • Create tag ${tagName}`); + console.log(''); + console.log('📋 Commands that would work:'); + if (isRepoDirty || needsPackageUpdate) { + console.log(` node scripts/new-version.js ${targetVersion} --force`); + } else { + console.log(` node scripts/new-version.js ${targetVersion}`); + console.log(` node scripts/new-version.js ${targetVersion} --force`); + } + } else { + console.log('⚡ Actions needed:'); + console.log(` • Create tag ${tagName} (no commit needed)`); + console.log(''); + console.log('📋 Commands that would work:'); + console.log(` node scripts/new-version.js ${targetVersion}`); + console.log(` node scripts/new-version.js ${targetVersion} --force`); + } + + console.log(''); + console.log('🚦 Default mode requirements:'); + if (isRepoDirty) { + console.log(' ❌ Repository must be clean (currently dirty)'); + } else { + console.log(' ✅ Repository is clean'); + } + if (!packageJsonMatches) { + console.log(` ❌ Package.json must match version (currently ${currentVersion})`); + } else { + console.log(' ✅ Package.json version matches'); + } + + } else { + // This should never happen since version is now required + console.error('Internal error: No version provided to performCheck'); + process.exit(1); + } + + } catch (error) { + console.error('❌ Error during analysis:', error.message); + process.exit(1); + } } function main() { // Parse command line arguments const args = process.argv.slice(2); - if (args.length === 0 || args[0] === '-h' || args[0] === '--help') { + if (args.length === 0 || args.includes('-h') || args.includes('--help')) { showUsage(); process.exit(args.length === 0 ? 1 : 0); } - if (args.length !== 1) { - console.error('Error: Exactly one version argument required'); - showUsage(); - process.exit(1); + const isCheck = args.includes('--check'); + const isForce = args.includes('--force'); + + let newVersion; + if (isCheck) { + // For --check, version is required + newVersion = args.find(arg => !arg.startsWith('--')); + if (!newVersion) { + console.error('Error: Version argument required for --check'); + showUsage(); + process.exit(1); + } + } else { + // For normal operation, version is required + newVersion = args[0]; + if (!newVersion || newVersion.startsWith('-')) { + console.error('Error: Version argument required'); + showUsage(); + process.exit(1); + } + } + + if (isCheck) { + performCheck(newVersion); + return; } - const newVersion = args[0]; const tagName = `v${newVersion}`; - console.log(`🏷️ Creating new version: ${newVersion}`); + console.log(`🏷️ Creating new version: ${newVersion}${isForce ? ' (forced)' : ''}`); try { - // Check if tag already exists + // 1. Check if tag already exists - Always ERROR try { const existingTags = execSync('git tag -l', { encoding: 'utf8' }); if (existingTags.split('\n').includes(tagName)) { @@ -46,34 +219,63 @@ function main() { process.exit(1); } - // Check if working directory is clean + // 2. Check repository status + let isRepoDirty = false; try { const status = execSync('git status --porcelain', { encoding: 'utf8' }); - if (status.trim()) { - console.error('❌ Error: Working directory has uncommitted changes'); - console.error('Please commit or stash your changes first'); - process.exit(1); - } + isRepoDirty = status.trim() !== ''; } catch (error) { console.error('❌ Error: Failed to check git status'); process.exit(1); } - // Read and update package.json + // 3. Check package.json version const packagePath = './package.json'; const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8')); - const oldVersion = pkg.version; + const currentVersion = pkg.version; + const packageJsonMatches = currentVersion === newVersion; - pkg.version = newVersion; - fs.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + '\n'); - console.log(`📦 Updated package.json: ${oldVersion} → ${newVersion}`); + // 4. Determine what action is needed + const needsPackageUpdate = !packageJsonMatches; + const needsCommit = isRepoDirty || needsPackageUpdate; - // Commit the package.json change - execSync('git add package.json', { stdio: 'inherit' }); - execSync(`git commit -m "Bump version to ${newVersion}"`, { stdio: 'inherit' }); - console.log(`✅ Committed version change`); + // 5. Check if force is required + if (!isForce) { + if (isRepoDirty) { + console.error('❌ Error: Working directory has uncommitted changes'); + console.error('Please commit your changes first or use --force'); + process.exit(1); + } + if (needsPackageUpdate) { + console.error(`❌ Error: Package.json version is ${currentVersion}, requested ${newVersion}`); + console.error('Use --force to update package.json'); + process.exit(1); + } + } - // Tag the commit + // 6. Execute the versioning + if (needsCommit) { + console.log(`📦 Needs commit: ${needsPackageUpdate ? 'package.json update' : ''}${needsPackageUpdate && isRepoDirty ? ' + ' : ''}${isRepoDirty ? 'uncommitted changes' : ''}`); + + // Update package.json if needed + if (needsPackageUpdate) { + pkg.version = newVersion; + fs.writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + '\n'); + console.log(`📝 Updated package.json: ${currentVersion} → ${newVersion}`); + } + + // Stage all changes + execSync('git add .', { stdio: 'inherit' }); + + // Commit + const commitMessage = needsPackageUpdate ? `Version ${newVersion}` : `Prepare for version ${newVersion}`; + execSync(`git commit -m "${commitMessage}"`, { stdio: 'inherit' }); + console.log(`✅ Committed changes`); + } else { + console.log(`✅ Repository clean, package.json matches - tagging current commit`); + } + + // 7. Tag the commit execSync(`git tag ${tagName}`, { stdio: 'inherit' }); console.log(`🏷️ Created tag: ${tagName}`);