Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48305ebb6a | |||
| 485c0a3855 | |||
| adc828d9bb | |||
| fff1d39338 |
19
changelog.md
19
changelog.md
@@ -1,5 +1,24 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-11-06 - 1.20.0 - feat(commit)
|
||||||
|
Add non-interactive --yes (-y) flag to commit command to auto-accept AI recommendations and optionally push with -p
|
||||||
|
|
||||||
|
- Add -y / --yes flag to gitzone commit to auto-accept AI-generated commit recommendations without interactive prompts
|
||||||
|
- Support -yp or -y -p combinations to auto-accept and push to origin; -p / --push remains the separate control for pushing
|
||||||
|
- Implementation creates a smartinteract AnswerBucket programmatically when -y is used and populates commitType, commitScope, commitDescription and pushToOrigin
|
||||||
|
- Preserves existing UI output and interactive flow when -y is not used; fully backward compatible and CI/CD friendly
|
||||||
|
- Updated CLI usage and documentation (readme.hints.md) to document the new flags
|
||||||
|
|
||||||
|
## 2025-11-05 - 1.19.9 - fix(mod_commit)
|
||||||
|
Refactor version bumping to a unified implementation for npm and Deno; remove npm-exec based helpers and add file-based version readers/updaters to avoid npm warning pollution
|
||||||
|
|
||||||
|
- Removed legacy npm/deno-specific helpers (bumpNpmVersion, syncVersionToDenoJson, bumpDenoVersion) that relied on executing npm and caused warning pollution
|
||||||
|
- Added readCurrentVersion() to read version from package.json or deno.json
|
||||||
|
- Added updateVersionFile() helper to write version directly into JSON files
|
||||||
|
- Added unified bumpProjectVersion() that handles npm, deno and both with a single code path; reuses calculateNewVersion()
|
||||||
|
- Stages updated files, commits v<newVersion> and creates a tag v<newVersion>
|
||||||
|
- Benefits: no npm warning pollution in deno.json, simpler git history, consistent behavior across project types
|
||||||
|
|
||||||
## 2025-11-04 - 1.19.8 - fix(package.json)
|
## 2025-11-04 - 1.19.8 - fix(package.json)
|
||||||
Bump @git.zone/tsdoc dependency to ^1.9.2
|
Bump @git.zone/tsdoc dependency to ^1.9.2
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@git.zone/cli",
|
"name": "@git.zone/cli",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.19.8",
|
"version": "1.20.0",
|
||||||
"description": "A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.",
|
"description": "A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.",
|
||||||
"main": "dist_ts/index.ts",
|
"main": "dist_ts/index.ts",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
|
|||||||
@@ -89,6 +89,41 @@ The format module is responsible for project standardization:
|
|||||||
5. **Performance Optimizations**: Parallel execution and caching
|
5. **Performance Optimizations**: Parallel execution and caching
|
||||||
6. **Reporting**: Diff views, statistics, verbose logging
|
6. **Reporting**: Diff views, statistics, verbose logging
|
||||||
7. **Architecture**: Clean separation of concerns with new classes
|
7. **Architecture**: Clean separation of concerns with new classes
|
||||||
|
8. **Unified Version Bumping**: Self-managed version updates eliminating npm warning pollution in deno.json
|
||||||
|
|
||||||
|
### Version Bumping Refactor (Latest)
|
||||||
|
|
||||||
|
The commit module's version bumping has been refactored to eliminate npm command dependencies:
|
||||||
|
|
||||||
|
**Changes:**
|
||||||
|
- Removed `bumpNpmVersion()` - was causing npm warnings to pollute deno.json
|
||||||
|
- Removed `syncVersionToDenoJson()` - no longer needed with unified approach
|
||||||
|
- Removed separate `bumpDenoVersion()` - replaced by unified implementation
|
||||||
|
- Added `readCurrentVersion()` helper - reads from either package.json or deno.json
|
||||||
|
- Added `updateVersionFile()` helper - updates JSON files directly
|
||||||
|
- Unified `bumpProjectVersion()` - handles npm/deno/both with single clean code path
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- No npm warning pollution in version fields
|
||||||
|
- Full control over version bumping process
|
||||||
|
- Simpler git history (no amending, no force-tagging)
|
||||||
|
- Same code path for all project types
|
||||||
|
- Reuses existing `calculateNewVersion()` function
|
||||||
|
|
||||||
|
### Auto-Accept Flag for Commits
|
||||||
|
|
||||||
|
The commit module now supports `-y/--yes` flag for non-interactive commits:
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
- `gitzone commit -y` - Auto-accepts AI recommendations without prompts
|
||||||
|
- `gitzone commit -yp` - Auto-accepts and pushes to origin
|
||||||
|
- Separate `-p/--push` flag controls push behavior
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
- Creates AnswerBucket programmatically when `-y` flag detected
|
||||||
|
- Preserves all UI output for transparency
|
||||||
|
- Fully backward compatible with interactive mode
|
||||||
|
- CI/CD friendly for automated workflows
|
||||||
|
|
||||||
## Development Tips
|
## Development Tips
|
||||||
|
|
||||||
@@ -137,6 +172,27 @@ The format module is responsible for project standardization:
|
|||||||
|
|
||||||
## CLI Usage
|
## CLI Usage
|
||||||
|
|
||||||
|
### Commit Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Interactive commit (default)
|
||||||
|
gitzone commit
|
||||||
|
|
||||||
|
# Auto-accept AI recommendations (no prompts)
|
||||||
|
gitzone commit -y
|
||||||
|
gitzone commit --yes
|
||||||
|
|
||||||
|
# Auto-accept and push to origin
|
||||||
|
gitzone commit -yp
|
||||||
|
gitzone commit -y -p
|
||||||
|
gitzone commit --yes --push
|
||||||
|
|
||||||
|
# Run format before commit
|
||||||
|
gitzone commit --format
|
||||||
|
```
|
||||||
|
|
||||||
|
### Format Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Basic format
|
# Basic format
|
||||||
gitzone format
|
gitzone format
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/cli',
|
name: '@git.zone/cli',
|
||||||
version: '1.19.8',
|
version: '1.20.0',
|
||||||
description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.'
|
description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,35 +27,63 @@ export const run = async (argvArg: any) => {
|
|||||||
recommendedNextVersionScope: nextCommitObject.recommendedNextVersionScope,
|
recommendedNextVersionScope: nextCommitObject.recommendedNextVersionScope,
|
||||||
recommendedNextVersionMessage: nextCommitObject.recommendedNextVersionMessage,
|
recommendedNextVersionMessage: nextCommitObject.recommendedNextVersionMessage,
|
||||||
});
|
});
|
||||||
const commitInteract = new plugins.smartinteract.SmartInteract();
|
|
||||||
commitInteract.addQuestions([
|
let answerBucket: plugins.smartinteract.AnswerBucket;
|
||||||
{
|
|
||||||
type: 'list',
|
// Check if -y or --yes flag is set to auto-accept recommendations
|
||||||
name: `commitType`,
|
if (argvArg.y || argvArg.yes) {
|
||||||
message: `Choose TYPE of the commit:`,
|
// Auto-mode: create AnswerBucket programmatically
|
||||||
choices: [`fix`, `feat`, `BREAKING CHANGE`],
|
logger.log('info', '✓ Auto-accepting AI recommendations (--yes flag)');
|
||||||
default: nextCommitObject.recommendedNextVersionLevel,
|
|
||||||
},
|
answerBucket = new plugins.smartinteract.AnswerBucket();
|
||||||
{
|
answerBucket.addAnswer({
|
||||||
type: 'input',
|
name: 'commitType',
|
||||||
name: `commitScope`,
|
value: nextCommitObject.recommendedNextVersionLevel,
|
||||||
message: `What is the SCOPE of the commit:`,
|
});
|
||||||
default: nextCommitObject.recommendedNextVersionScope,
|
answerBucket.addAnswer({
|
||||||
},
|
name: 'commitScope',
|
||||||
{
|
value: nextCommitObject.recommendedNextVersionScope,
|
||||||
type: `input`,
|
});
|
||||||
name: `commitDescription`,
|
answerBucket.addAnswer({
|
||||||
message: `What is the DESCRIPTION of the commit?`,
|
name: 'commitDescription',
|
||||||
default: nextCommitObject.recommendedNextVersionMessage,
|
value: nextCommitObject.recommendedNextVersionMessage,
|
||||||
},
|
});
|
||||||
{
|
answerBucket.addAnswer({
|
||||||
type: 'confirm',
|
name: 'pushToOrigin',
|
||||||
name: `pushToOrigin`,
|
value: !!(argvArg.p || argvArg.push), // Only push if -p flag also provided
|
||||||
message: `Do you want to push this version now?`,
|
});
|
||||||
default: true,
|
} else {
|
||||||
},
|
// Interactive mode: prompt user for input
|
||||||
]);
|
const commitInteract = new plugins.smartinteract.SmartInteract();
|
||||||
const answerBucket = await commitInteract.runQueue();
|
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,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
answerBucket = await commitInteract.runQueue();
|
||||||
|
}
|
||||||
const commitString = createCommitStringFromAnswerBucket(answerBucket);
|
const commitString = createCommitStringFromAnswerBucket(answerBucket);
|
||||||
const commitVersionType = (() => {
|
const commitVersionType = (() => {
|
||||||
switch (answerBucket.getAnswerFor('commitType')) {
|
switch (answerBucket.getAnswerFor('commitType')) {
|
||||||
|
|||||||
@@ -91,118 +91,47 @@ function calculateNewVersion(currentVersion: string, versionType: VersionType):
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bumps the version in deno.json, commits the change, and creates a tag
|
* Reads the current version from package.json or deno.json
|
||||||
* @param versionType Type of version bump
|
* @param projectType The project type to determine which file to read
|
||||||
* @returns The new version string
|
* @returns The current version string
|
||||||
*/
|
*/
|
||||||
export async function bumpDenoVersion(versionType: VersionType): Promise<string> {
|
function readCurrentVersion(projectType: ProjectType): string {
|
||||||
const denoJsonPath = plugins.path.join(paths.cwd, 'deno.json');
|
if (projectType === 'npm' || projectType === 'both') {
|
||||||
const smartshellInstance = new plugins.smartshell.Smartshell({
|
const packageJsonPath = plugins.path.join(paths.cwd, 'package.json');
|
||||||
executor: 'bash',
|
const packageJson = plugins.smartfile.fs.toObjectSync(packageJsonPath) as { version?: string };
|
||||||
sourceFilePaths: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
if (!packageJson.version) {
|
||||||
// Read deno.json
|
throw new Error('package.json does not contain a version field');
|
||||||
const denoConfig = plugins.smartfile.fs.toObjectSync(
|
}
|
||||||
denoJsonPath
|
return packageJson.version;
|
||||||
) as { version?: string };
|
} else {
|
||||||
|
const denoJsonPath = plugins.path.join(paths.cwd, 'deno.json');
|
||||||
|
const denoConfig = plugins.smartfile.fs.toObjectSync(denoJsonPath) as { version?: string };
|
||||||
|
|
||||||
if (!denoConfig.version) {
|
if (!denoConfig.version) {
|
||||||
throw new Error('deno.json does not contain a version field');
|
throw new Error('deno.json does not contain a version field');
|
||||||
}
|
}
|
||||||
|
return denoConfig.version;
|
||||||
const currentVersion = denoConfig.version;
|
|
||||||
const newVersion = calculateNewVersion(currentVersion, versionType);
|
|
||||||
|
|
||||||
logger.log('info', `Bumping deno.json version: ${currentVersion} → ${newVersion}`);
|
|
||||||
|
|
||||||
// Update version
|
|
||||||
denoConfig.version = newVersion;
|
|
||||||
|
|
||||||
// Write back to disk
|
|
||||||
await plugins.smartfile.memory.toFs(
|
|
||||||
JSON.stringify(denoConfig, null, 2) + '\n',
|
|
||||||
denoJsonPath
|
|
||||||
);
|
|
||||||
|
|
||||||
// Stage the deno.json file
|
|
||||||
await smartshellInstance.exec('git add deno.json');
|
|
||||||
|
|
||||||
// Commit the version bump
|
|
||||||
await smartshellInstance.exec(`git commit -m "v${newVersion}"`);
|
|
||||||
|
|
||||||
// Create the version tag
|
|
||||||
await smartshellInstance.exec(`git tag v${newVersion} -m "v${newVersion}"`);
|
|
||||||
|
|
||||||
logger.log('info', `Created commit and tag v${newVersion}`);
|
|
||||||
|
|
||||||
return newVersion;
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(`Failed to bump deno.json version: ${error.message}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bumps the version in package.json using npm version command
|
* Updates the version field in a JSON file (package.json or deno.json)
|
||||||
* @param versionType Type of version bump
|
* @param filePath Path to the JSON file
|
||||||
* @returns The new version string
|
* @param newVersion The new version to write
|
||||||
*/
|
*/
|
||||||
async function bumpNpmVersion(versionType: VersionType): Promise<string> {
|
async function updateVersionFile(filePath: string, newVersion: string): Promise<void> {
|
||||||
const smartshellInstance = new plugins.smartshell.Smartshell({
|
const config = plugins.smartfile.fs.toObjectSync(filePath) as { version?: string };
|
||||||
executor: 'bash',
|
config.version = newVersion;
|
||||||
sourceFilePaths: [],
|
await plugins.smartfile.memory.toFs(
|
||||||
});
|
JSON.stringify(config, null, 2) + '\n',
|
||||||
|
filePath
|
||||||
logger.log('info', `Bumping package.json version using npm version ${versionType}`);
|
);
|
||||||
const result = await smartshellInstance.exec(`npm version ${versionType}`);
|
|
||||||
|
|
||||||
// npm version returns the new version with a 'v' prefix, e.g., "v1.2.3"
|
|
||||||
const newVersion = result.stdout.trim().replace(/^v/, '');
|
|
||||||
return newVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Syncs the version from package.json to deno.json and amends the npm commit
|
|
||||||
* @param version The version to sync
|
|
||||||
*/
|
|
||||||
async function syncVersionToDenoJson(version: string): Promise<void> {
|
|
||||||
const denoJsonPath = plugins.path.join(paths.cwd, 'deno.json');
|
|
||||||
const smartshellInstance = new plugins.smartshell.Smartshell({
|
|
||||||
executor: 'bash',
|
|
||||||
sourceFilePaths: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const denoConfig = plugins.smartfile.fs.toObjectSync(
|
|
||||||
denoJsonPath
|
|
||||||
) as { version?: string };
|
|
||||||
|
|
||||||
logger.log('info', `Syncing version to deno.json: ${version}`);
|
|
||||||
denoConfig.version = version;
|
|
||||||
|
|
||||||
await plugins.smartfile.memory.toFs(
|
|
||||||
JSON.stringify(denoConfig, null, 2) + '\n',
|
|
||||||
denoJsonPath
|
|
||||||
);
|
|
||||||
|
|
||||||
// Stage the deno.json file
|
|
||||||
await smartshellInstance.exec('git add deno.json');
|
|
||||||
|
|
||||||
// Amend the npm version commit to include deno.json
|
|
||||||
await smartshellInstance.exec('git commit --amend --no-edit');
|
|
||||||
|
|
||||||
// Re-create the tag with force to update it
|
|
||||||
await smartshellInstance.exec(`git tag -fa v${version} -m "v${version}"`);
|
|
||||||
|
|
||||||
logger.log('info', `Amended commit to include deno.json and updated tag v${version}`);
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(`Failed to sync version to deno.json: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bumps the project version based on project type
|
* Bumps the project version based on project type
|
||||||
|
* Handles npm-only, deno-only, and dual projects with unified logic
|
||||||
* @param projectType The detected project type
|
* @param projectType The detected project type
|
||||||
* @param versionType The type of version bump
|
* @param versionType The type of version bump
|
||||||
* @param currentStep The current step number for progress display
|
* @param currentStep The current step number for progress display
|
||||||
@@ -215,6 +144,10 @@ export async function bumpProjectVersion(
|
|||||||
currentStep?: number,
|
currentStep?: number,
|
||||||
totalSteps?: number
|
totalSteps?: number
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
|
if (projectType === 'none') {
|
||||||
|
throw new Error('Cannot bump version: no package.json or deno.json found');
|
||||||
|
}
|
||||||
|
|
||||||
const projectEmoji = projectType === 'npm' ? '📦' : projectType === 'deno' ? '🦕' : '🔀';
|
const projectEmoji = projectType === 'npm' ? '📦' : projectType === 'deno' ? '🦕' : '🔀';
|
||||||
const description = `🏷️ Bumping version (${projectEmoji} ${projectType})`;
|
const description = `🏷️ Bumping version (${projectEmoji} ${projectType})`;
|
||||||
|
|
||||||
@@ -222,35 +155,52 @@ export async function bumpProjectVersion(
|
|||||||
ui.printStep(currentStep, totalSteps, description, 'in-progress');
|
ui.printStep(currentStep, totalSteps, description, 'in-progress');
|
||||||
}
|
}
|
||||||
|
|
||||||
let newVersion: string;
|
const smartshellInstance = new plugins.smartshell.Smartshell({
|
||||||
|
executor: 'bash',
|
||||||
|
sourceFilePaths: [],
|
||||||
|
});
|
||||||
|
|
||||||
switch (projectType) {
|
try {
|
||||||
case 'npm':
|
// 1. Read current version
|
||||||
newVersion = await bumpNpmVersion(versionType);
|
const currentVersion = readCurrentVersion(projectType);
|
||||||
break;
|
|
||||||
|
|
||||||
case 'deno':
|
// 2. Calculate new version (reuse existing function!)
|
||||||
newVersion = await bumpDenoVersion(versionType);
|
const newVersion = calculateNewVersion(currentVersion, versionType);
|
||||||
break;
|
|
||||||
|
|
||||||
case 'both': {
|
logger.log('info', `Bumping version: ${currentVersion} → ${newVersion}`);
|
||||||
// Bump npm version first (it handles git tags)
|
|
||||||
newVersion = await bumpNpmVersion(versionType);
|
// 3. Determine which files to update
|
||||||
// Then sync to deno.json
|
const filesToUpdate: string[] = [];
|
||||||
await syncVersionToDenoJson(newVersion);
|
const packageJsonPath = plugins.path.join(paths.cwd, 'package.json');
|
||||||
break;
|
const denoJsonPath = plugins.path.join(paths.cwd, 'deno.json');
|
||||||
|
|
||||||
|
if (projectType === 'npm' || projectType === 'both') {
|
||||||
|
await updateVersionFile(packageJsonPath, newVersion);
|
||||||
|
filesToUpdate.push('package.json');
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'none':
|
if (projectType === 'deno' || projectType === 'both') {
|
||||||
throw new Error('Cannot bump version: no package.json or deno.json found');
|
await updateVersionFile(denoJsonPath, newVersion);
|
||||||
|
filesToUpdate.push('deno.json');
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
// 4. Stage all updated files
|
||||||
throw new Error(`Unknown project type: ${projectType}`);
|
await smartshellInstance.exec(`git add ${filesToUpdate.join(' ')}`);
|
||||||
|
|
||||||
|
// 5. Create version commit
|
||||||
|
await smartshellInstance.exec(`git commit -m "v${newVersion}"`);
|
||||||
|
|
||||||
|
// 6. Create version tag
|
||||||
|
await smartshellInstance.exec(`git tag v${newVersion} -m "v${newVersion}"`);
|
||||||
|
|
||||||
|
logger.log('info', `Created commit and tag v${newVersion}`);
|
||||||
|
|
||||||
|
if (currentStep && totalSteps) {
|
||||||
|
ui.printStep(currentStep, totalSteps, description, 'done');
|
||||||
|
}
|
||||||
|
|
||||||
|
return newVersion;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to bump project version: ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentStep && totalSteps) {
|
|
||||||
ui.printStep(currentStep, totalSteps, description, 'done');
|
|
||||||
}
|
|
||||||
|
|
||||||
return newVersion;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user