UNPKG

post-merge

Version:

A reusable library for handling post-merge operations including version bumping and git tagging

245 lines (244 loc) 10.7 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const index_1 = require("./index"); const config_utils_1 = require("./config-utils"); const init_utils_1 = require("./init-utils"); /** * Get package version from package.json */ function getPackageVersion() { try { const packageJson = require('../package.json'); return packageJson.version; } catch (error) { return '1.0.0'; // fallback version } } /** * Setup Commander.js program */ function setupCommander() { const configExists = (0, config_utils_1.configFileExists)(); const program = new commander_1.Command(); program .name('post-merge') .description('Hotfix Post-Merge CLI for GitLab CI automation') .version(getPackageVersion()) .addHelpText('before', ` Configuration: Config file: ${config_utils_1.CONFIG_FILE_NAME} ${configExists ? '✅ Found' : '❌ Not found'} Precedence: defaults < config file < CLI arguments < environment variables Environment Variables: CI_PIPELINE_SOURCE Should be 'push' for hotfix detection CI_COMMIT_BRANCH Should match TEST_hotfix/Hotfix-YYYYMMDD pattern CI_COMMIT_MESSAGE Should contain 'Merge branch' for hotfix detection CI_PUSH_TOKEN Git access token for pushing changes CI_SERVER_HOST GitLab server hostname CI_PROJECT_PATH Project path for git operations GITLAB_USER_NAME Git user name GITLAB_USER_EMAIL Git user email `); // Global options for post-merge execution program .option('--package-json <path>', 'Path to package.json (default: ./package.json)') .option('--branch <name>', 'Branch name (default: CI_COMMIT_BRANCH)') .option('--access-token <token>', 'Git access token (default: CI_PUSH_TOKEN)') .option('--no-tags', "Don't create and push git tags") .option('--version-strategy <type>', 'Version bump strategy: patch, prerelease, auto (default: auto)', (value) => { if (!['patch', 'prerelease', 'auto'].includes(value)) { throw new Error('Invalid version strategy. Use: patch, prerelease, or auto'); } return value; }) .option('--prerelease-id <id>', 'Prerelease identifier (default: release)') .option('--commit-template <msg>', 'Commit message template, use {version} placeholder') .option('--git-user-name <name>', 'Git user name (default: GITLAB_USER_NAME)') .option('--git-user-email <email>', 'Git user email (default: GITLAB_USER_EMAIL)') .option('--check-conditions', 'Check if current environment meets hotfix conditions'); // Execute command program .command('execute') .description('Execute the main post-merge automation process') .option('--package-json <path>', 'Path to package.json (default: ./package.json)') .option('--branch <name>', 'Branch name (default: CI_COMMIT_BRANCH)') .option('--access-token <token>', 'Git access token (default: CI_PUSH_TOKEN)') .option('--no-tags', "Don't create and push git tags") .option('--version-strategy <type>', 'Version bump strategy: patch, prerelease, auto (default: auto)', (value) => { if (!['patch', 'prerelease', 'auto'].includes(value)) { throw new Error('Invalid version strategy. Use: patch, prerelease, or auto'); } return value; }) .option('--prerelease-id <id>', 'Prerelease identifier (default: release)') .option('--commit-template <msg>', 'Commit message template, use {version} placeholder') .option('--git-user-name <name>', 'Git user name (default: GITLAB_USER_NAME)') .option('--git-user-email <email>', 'Git user email (default: GITLAB_USER_EMAIL)') .addHelpText('after', ` Examples: $ post-merge execute # Basic execution $ post-merge execute --version-strategy patch # Force patch version bump $ post-merge execute --no-tags # Skip creating git tags $ post-merge execute --commit-template "chore: bump to {version} [skip ci]" `) .action(async (options) => { await executePostMerge(options); }); // Init command program .command('init') .description('Initialize GitLab CI configuration and scripts') .option('--branch-pattern <pattern>', 'Branch pattern for triggering post-merge (e.g., "^hotfix/.*$")') .option('--nodejs-image-url <url>', 'Node.js Docker image URL for GitLab CI') .addHelpText('after', ` Examples: $ post-merge init # Interactive mode $ post-merge init --branch-pattern "^hotfix/.*$" # With custom branch pattern $ post-merge init --nodejs-image-url node:16 # With custom Node.js image $ post-merge init --branch-pattern "^release/v\\d+\\.\\d+$" --nodejs-image-url node:18 `) .action(async (options) => { await runInit(options.branchPattern, options.nodejsImageUrl); }); // Check conditions command program .command('check') .description('Check if current environment meets hotfix conditions') .action(() => { checkConditions(); }); return program; } /** * Execute the main post-merge automation process */ async function executePostMerge(options) { try { // Extract CLI options into config format const cliConfig = {}; if (options.packageJson) cliConfig.packageJsonPath = options.packageJson; if (options.branch) cliConfig.branchName = options.branch; if (options.accessToken) cliConfig.accessToken = options.accessToken; if (options.tags === false) cliConfig.createTags = false; if (options.versionStrategy) cliConfig.versionStrategy = options.versionStrategy; if (options.prereleaseId) cliConfig.prereleaseId = options.prereleaseId; if (options.commitTemplate) cliConfig.commitMessageTemplate = options.commitTemplate; if (options.gitUserName) cliConfig.gitUserName = options.gitUserName; if (options.gitUserEmail) cliConfig.gitUserEmail = options.gitUserEmail; // Load configuration with proper precedence: defaults < config file < CLI args const config = (0, config_utils_1.loadConfiguration)(cliConfig); // Check if we should execute based on CI conditions if (!index_1.PostMergeHandler.shouldExecute()) { console.log('post-merge conditions not met. Use "post-merge check" to see details.'); process.exit(0); } const handler = new index_1.PostMergeHandler(config); const result = await handler.execute(); if (result.success) { console.log('\\n✅ Hotfix post-merge process completed successfully!'); console.log(`Version updated: ${result.versionInfo.currentVersion}${result.versionInfo.newVersion}`); if (result.tagName) { console.log(`Tag created: ${result.tagName}`); } process.exit(0); } else { console.error('\\n❌ Hotfix post-merge process failed!'); console.error(`Error: ${result.error}`); process.exit(1); } } catch (error) { console.error('\\n❌ Post-merge execution failed!'); console.error(error instanceof Error ? error.message : String(error)); process.exit(1); } } /** * Check and print whether conditions are met for hotfix execution */ function checkConditions() { const shouldExecute = index_1.PostMergeHandler.shouldExecute(); console.log('Hotfix Conditions Check:'); console.log('======================='); console.log(`Pipeline Source: ${process.env.CI_PIPELINE_SOURCE || 'Not set'}`); console.log(`Branch Name: ${process.env.CI_COMMIT_BRANCH || 'Not set'}`); console.log(`Commit Message: ${process.env.CI_COMMIT_MESSAGE || 'Not set'}`); console.log(`Should Execute: ${shouldExecute ? 'YES' : 'NO'}`); if (!shouldExecute) { console.log('\\nConditions for hotfix execution are not met.'); console.log('Requirements:'); console.log('- CI_PIPELINE_SOURCE must be "push"'); console.log('- CI_COMMIT_BRANCH must match pattern: TEST_hotfix/Hotfix-YYYYMMDD'); console.log('- CI_COMMIT_MESSAGE must contain "Merge branch"'); } } /** * Initialize GitLab CI configuration and script files */ async function runInit(branchPattern, nodejsImageUrl) { console.log('Initializing post-merge configuration...'); try { const result = await (0, init_utils_1.initializePostMerge)({ branchPattern, interactive: !branchPattern, // Only prompt if no pattern provided nodejsImageUrl: nodejsImageUrl, }); console.log(result.message); if (result.success) { console.log('\n✅ Initialization completed successfully!'); console.log('\nNext steps:'); console.log('1. Review the generated files:'); console.log(' - .gitlab-ci.yml (or updated existing file)'); console.log(' - scripts/post-merge.sh'); console.log('2. Commit and push these changes to your repository'); console.log('3. The post-merge process will run automatically on hotfix merges'); process.exit(0); } else { console.error('\n❌ Initialization completed with errors'); process.exit(1); } } catch (error) { console.error('\n❌ Initialization failed!'); console.error(error instanceof Error ? error.message : String(error)); process.exit(1); } } /** * Main CLI execution */ async function main() { try { const program = setupCommander(); // Handle --check-conditions as a global option if (process.argv.includes('--check-conditions')) { checkConditions(); process.exit(0); } // Parse arguments await program.parseAsync(process.argv); } catch (error) { console.error('\\n❌ CLI execution failed!'); console.error(error instanceof Error ? error.message : String(error)); process.exit(1); } } // Execute main function if this file is run directly if (require.main === module) { main(); } //# sourceMappingURL=cli.js.map