179 lines
6.2 KiB
TypeScript
179 lines
6.2 KiB
TypeScript
// this file contains code to create commits in a consistent way
|
|
|
|
import * as plugins from './mod.plugins.js';
|
|
import * as paths from '../paths.js';
|
|
import { logger } from '../gitzone.logging.js';
|
|
import * as helpers from './mod.helpers.js';
|
|
import * as ui from './mod.ui.js';
|
|
|
|
export const run = async (argvArg: any) => {
|
|
if (argvArg.format) {
|
|
const formatMod = await import('../mod_format/index.js');
|
|
await formatMod.run();
|
|
}
|
|
|
|
ui.printHeader('🔍 Analyzing repository changes...');
|
|
|
|
const aidoc = new plugins.tsdoc.AiDoc();
|
|
await aidoc.start();
|
|
|
|
const nextCommitObject = await aidoc.buildNextCommitObject(paths.cwd);
|
|
|
|
await aidoc.stop();
|
|
|
|
ui.printRecommendation({
|
|
recommendedNextVersion: nextCommitObject.recommendedNextVersion,
|
|
recommendedNextVersionLevel: nextCommitObject.recommendedNextVersionLevel,
|
|
recommendedNextVersionScope: nextCommitObject.recommendedNextVersionScope,
|
|
recommendedNextVersionMessage: nextCommitObject.recommendedNextVersionMessage,
|
|
});
|
|
const commitInteract = new plugins.smartinteract.SmartInteract();
|
|
commitInteract.addQuestions([
|
|
{
|
|
type: 'list',
|
|
name: `commitType`,
|
|
message: `Choose TYPE of the commit:`,
|
|
choices: [`fix`, `feat`, `BREAKING CHANGE`],
|
|
default: nextCommitObject.recommendedNextVersionLevel,
|
|
},
|
|
{
|
|
type: 'input',
|
|
name: `commitScope`,
|
|
message: `What is the SCOPE of the commit:`,
|
|
default: nextCommitObject.recommendedNextVersionScope,
|
|
},
|
|
{
|
|
type: `input`,
|
|
name: `commitDescription`,
|
|
message: `What is the DESCRIPTION of the commit?`,
|
|
default: nextCommitObject.recommendedNextVersionMessage,
|
|
},
|
|
{
|
|
type: 'confirm',
|
|
name: `pushToOrigin`,
|
|
message: `Do you want to push this version now?`,
|
|
default: true,
|
|
},
|
|
]);
|
|
const answerBucket = await commitInteract.runQueue();
|
|
const commitString = createCommitStringFromAnswerBucket(answerBucket);
|
|
const commitVersionType = (() => {
|
|
switch (answerBucket.getAnswerFor('commitType')) {
|
|
case 'fix':
|
|
return 'patch';
|
|
case 'feat':
|
|
return 'minor';
|
|
case 'BREAKING CHANGE':
|
|
return 'major';
|
|
}
|
|
})();
|
|
|
|
ui.printHeader('✨ Creating Semantic Commit');
|
|
ui.printCommitMessage(commitString);
|
|
const smartshellInstance = new plugins.smartshell.Smartshell({
|
|
executor: 'bash',
|
|
sourceFilePaths: [],
|
|
});
|
|
|
|
// Determine total steps (6 if pushing, 5 if not)
|
|
const totalSteps = answerBucket.getAnswerFor('pushToOrigin') && !(process.env.CI === 'true') ? 6 : 5;
|
|
let currentStep = 0;
|
|
|
|
// Step 1: Baking commitinfo
|
|
currentStep++;
|
|
ui.printStep(currentStep, totalSteps, '🔧 Baking commit info into code', 'in-progress');
|
|
const commitInfo = new plugins.commitinfo.CommitInfo(
|
|
paths.cwd,
|
|
commitVersionType,
|
|
);
|
|
await commitInfo.writeIntoPotentialDirs();
|
|
ui.printStep(currentStep, totalSteps, '🔧 Baking commit info into code', 'done');
|
|
|
|
// Step 2: Writing changelog
|
|
currentStep++;
|
|
ui.printStep(currentStep, totalSteps, '📄 Generating changelog.md', 'in-progress');
|
|
let changelog = nextCommitObject.changelog;
|
|
changelog = changelog.replaceAll(
|
|
'{{nextVersion}}',
|
|
(await commitInfo.getNextPlannedVersion()).versionString,
|
|
);
|
|
changelog = changelog.replaceAll(
|
|
'{{nextVersionScope}}',
|
|
`${await answerBucket.getAnswerFor('commitType')}(${await answerBucket.getAnswerFor('commitScope')})`,
|
|
);
|
|
changelog = changelog.replaceAll(
|
|
'{{nextVersionMessage}}',
|
|
nextCommitObject.recommendedNextVersionMessage,
|
|
);
|
|
if (nextCommitObject.recommendedNextVersionDetails?.length > 0) {
|
|
changelog = changelog.replaceAll(
|
|
'{{nextVersionDetails}}',
|
|
'- ' + nextCommitObject.recommendedNextVersionDetails.join('\n- '),
|
|
);
|
|
} else {
|
|
changelog = changelog.replaceAll('\n{{nextVersionDetails}}', '');
|
|
}
|
|
|
|
await plugins.smartfile.memory.toFs(
|
|
changelog,
|
|
plugins.path.join(paths.cwd, `changelog.md`),
|
|
);
|
|
ui.printStep(currentStep, totalSteps, '📄 Generating changelog.md', 'done');
|
|
|
|
// Step 3: Staging files
|
|
currentStep++;
|
|
ui.printStep(currentStep, totalSteps, '📦 Staging files', 'in-progress');
|
|
await smartshellInstance.exec(`git add -A`);
|
|
ui.printStep(currentStep, totalSteps, '📦 Staging files', 'done');
|
|
|
|
// Step 4: Creating commit
|
|
currentStep++;
|
|
ui.printStep(currentStep, totalSteps, '💾 Creating git commit', 'in-progress');
|
|
await smartshellInstance.exec(`git commit -m "${commitString}"`);
|
|
ui.printStep(currentStep, totalSteps, '💾 Creating git commit', 'done');
|
|
|
|
// Step 5: Bumping version
|
|
currentStep++;
|
|
const projectType = await helpers.detectProjectType();
|
|
const newVersion = await helpers.bumpProjectVersion(projectType, commitVersionType, currentStep, totalSteps);
|
|
|
|
// Step 6: Push to remote (optional)
|
|
const currentBranch = await helpers.detectCurrentBranch();
|
|
if (
|
|
answerBucket.getAnswerFor('pushToOrigin') &&
|
|
!(process.env.CI === 'true')
|
|
) {
|
|
currentStep++;
|
|
ui.printStep(currentStep, totalSteps, `🚀 Pushing to origin/${currentBranch}`, 'in-progress');
|
|
await smartshellInstance.exec(`git push origin ${currentBranch} --follow-tags`);
|
|
ui.printStep(currentStep, totalSteps, `🚀 Pushing to origin/${currentBranch}`, 'done');
|
|
}
|
|
|
|
console.log(''); // Add spacing before summary
|
|
|
|
// Get commit SHA for summary
|
|
const commitShaResult = await smartshellInstance.exec('git rev-parse --short HEAD');
|
|
const commitSha = commitShaResult.stdout.trim();
|
|
|
|
// Print final summary
|
|
ui.printSummary({
|
|
projectType,
|
|
branch: currentBranch,
|
|
commitType: answerBucket.getAnswerFor('commitType'),
|
|
commitScope: answerBucket.getAnswerFor('commitScope'),
|
|
commitMessage: answerBucket.getAnswerFor('commitDescription'),
|
|
newVersion: newVersion,
|
|
commitSha: commitSha,
|
|
pushed: answerBucket.getAnswerFor('pushToOrigin') && !(process.env.CI === 'true'),
|
|
});
|
|
};
|
|
|
|
const createCommitStringFromAnswerBucket = (
|
|
answerBucket: plugins.smartinteract.AnswerBucket,
|
|
) => {
|
|
const commitType = answerBucket.getAnswerFor('commitType');
|
|
const commitScope = answerBucket.getAnswerFor('commitScope');
|
|
const commitDescription = answerBucket.getAnswerFor('commitDescription');
|
|
return `${commitType}(${commitScope}): ${commitDescription}`;
|
|
};
|