UNPKG

@mseep/mcp-server-atlassian-bitbucket

Version:

Node.js/TypeScript MCP server for Atlassian Bitbucket. Enables AI systems (LLMs) to interact with workspaces, repositories, and pull requests via tools (list, get, comment, search). Connects AI directly to version control workflows through the standard MC

205 lines (177 loc) 5.52 kB
#!/usr/bin/env node /** * Script to update version numbers across the project * Usage: node scripts/update-version.js [version] [options] * Options: * --dry-run Show what changes would be made without applying them * --verbose Show detailed logging information * * If no version is provided, it will use the version from package.json */ import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; // Get the directory name of the current module const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const rootDir = path.resolve(__dirname, '..'); // Parse command line arguments const args = process.argv.slice(2); const options = { dryRun: args.includes('--dry-run'), verbose: args.includes('--verbose'), }; // Get the version (first non-flag argument) let newVersion = args.find((arg) => !arg.startsWith('--')); // Log helper function const log = (message, verbose = false) => { if (!verbose || options.verbose) { console.log(message); } }; // File paths that may contain version information const versionFiles = [ { path: path.join(rootDir, 'package.json'), pattern: /"version": "([^"]*)"/, replacement: (match, currentVersion) => match.replace(currentVersion, newVersion), }, { path: path.join(rootDir, 'src', 'utils', 'constants.util.ts'), pattern: /export const VERSION = ['"]([^'"]*)['"]/, replacement: (match, currentVersion) => match.replace(currentVersion, newVersion), }, // Also update the compiled JavaScript files if they exist { path: path.join(rootDir, 'dist', 'utils', 'constants.util.js'), pattern: /exports.VERSION = ['"]([^'"]*)['"]/, replacement: (match, currentVersion) => match.replace(currentVersion, newVersion), optional: true, // Mark this file as optional }, // Additional files can be added here with their patterns and replacement logic ]; /** * Read the version from package.json * @returns {string} The version from package.json */ function getPackageVersion() { try { const packageJsonPath = path.join(rootDir, 'package.json'); log(`Reading version from ${packageJsonPath}`, true); const packageJson = JSON.parse( fs.readFileSync(packageJsonPath, 'utf8'), ); if (!packageJson.version) { throw new Error('No version field found in package.json'); } return packageJson.version; } catch (error) { console.error(`Error reading package.json: ${error.message}`); process.exit(1); } } /** * Validate the semantic version format * @param {string} version - The version to validate * @returns {boolean} True if valid, throws error if invalid */ function validateVersion(version) { // More comprehensive semver regex const semverRegex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/; if (!semverRegex.test(version)) { throw new Error( `Invalid version format: ${version}\nPlease use semantic versioning format (e.g., 1.2.3, 1.2.3-beta.1, etc.)`, ); } return true; } /** * Update version in a specific file * @param {Object} fileConfig - Configuration for the file to update */ function updateFileVersion(fileConfig) { const { path: filePath, pattern, replacement, optional = false, } = fileConfig; try { log(`Checking ${filePath}...`, true); if (!fs.existsSync(filePath)) { if (optional) { log(`Optional file not found (skipping): ${filePath}`, true); return; } console.warn(`Warning: File not found: ${filePath}`); return; } // Read file content const fileContent = fs.readFileSync(filePath, 'utf8'); const match = fileContent.match(pattern); if (!match) { console.warn(`Warning: Version pattern not found in ${filePath}`); return; } const currentVersion = match[1]; if (currentVersion === newVersion) { log( `Version in ${path.basename(filePath)} is already ${newVersion}`, true, ); return; } // Create new content with the updated version const updatedContent = fileContent.replace(pattern, replacement); // Write the changes or log them in dry run mode if (options.dryRun) { log( `Would update version in ${filePath} from ${currentVersion} to ${newVersion}`, ); } else { // Create a backup of the original file fs.writeFileSync(`${filePath}.bak`, fileContent); log(`Backup created: ${filePath}.bak`, true); // Write the updated content fs.writeFileSync(filePath, updatedContent); log( `Updated version in ${path.basename(filePath)} from ${currentVersion} to ${newVersion}`, ); } } catch (error) { if (optional) { log(`Error with optional file ${filePath}: ${error.message}`, true); return; } console.error(`Error updating ${filePath}: ${error.message}`); process.exit(1); } } // Main execution try { // If no version specified, get from package.json if (!newVersion) { newVersion = getPackageVersion(); log( `No version specified, using version from package.json: ${newVersion}`, ); } // Validate the version format validateVersion(newVersion); // Update all configured files for (const fileConfig of versionFiles) { updateFileVersion(fileConfig); } if (options.dryRun) { log(`\nDry run completed. No files were modified.`); } else { log(`\nVersion successfully updated to ${newVersion}`); } } catch (error) { console.error(`\nVersion update failed: ${error.message}`); process.exit(1); }