126 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import * as plugins from '../plugins.js';
 | |
| import { AiDoc } from '../classes.aidoc.js';
 | |
| import { ProjectContext } from './projectcontext.js';
 | |
| 
 | |
| export interface INextCommitObject {
 | |
|   recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level of the project
 | |
|   recommendedNextVersionScope: string; // the recommended scope name of the next version, like "core" or "cli", or specific class names.
 | |
|   recommendedNextVersionMessage: string; // the commit message. Don't put fix() feat() or BREAKING CHANGE in the message. Please just the message itself.
 | |
|   recommendedNextVersionDetails: string[]; // detailed bullet points for the changelog
 | |
|   recommendedNextVersion: string; // the recommended next version of the project, x.x.x
 | |
|   changelog?: string; // the changelog for the next version
 | |
| }
 | |
| 
 | |
| export class Commit {
 | |
|   private aiDocsRef: AiDoc;
 | |
|   private projectDir: string;
 | |
| 
 | |
|   constructor(aiDocsRef: AiDoc, projectDirArg: string) {
 | |
|     this.aiDocsRef = aiDocsRef;
 | |
|     this.projectDir = projectDirArg;
 | |
|   }
 | |
| 
 | |
|   public async buildNextCommitObject(): Promise<INextCommitObject> {
 | |
|     const smartgitInstance = new plugins.smartgit.Smartgit();
 | |
|     await smartgitInstance.init();
 | |
|     const gitRepo = await plugins.smartgit.GitRepo.fromOpeningRepoDir(
 | |
|       smartgitInstance,
 | |
|       this.projectDir
 | |
|     );
 | |
|     const diffString = await gitRepo.getUncommittedDiff();
 | |
|     const projectContext = new ProjectContext(this.projectDir);
 | |
|     let contextString = await projectContext.update();
 | |
|     contextString = `
 | |
| ${contextString}
 | |
| 
 | |
| Below is the diff of the uncommitted changes. If nothing is changed, there are no changes:
 | |
| 
 | |
| ${diffString || 'No changes.'}
 | |
|     `;
 | |
| 
 | |
|     let result = await this.aiDocsRef.openaiInstance.chat({
 | |
|       systemMessage: `
 | |
| You create a commit message for a git commit.
 | |
| The commit message should be based on the files in the project.
 | |
| You should not include any licensing information.
 | |
| You should not include any personal information.
 | |
| 
 | |
| Important: Answer only in valid JSON.
 | |
| 
 | |
| Your answer should be parseable with JSON.parse() without modifying anything.
 | |
| 
 | |
| Here is the structure of the JSON you should return:
 | |
| 
 | |
| interface {
 | |
|   recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level of the project
 | |
|   recommendedNextVersionScope: string; // the recommended scope name of the next version, like "core" or "cli", or specific class names.
 | |
|   recommendedNextVersionMessage: string; // the commit message. Don't put fix() feat() or BREAKING CHANGE in the message. Please just the message itself.
 | |
|   recommendedNextVersionDetails: string[]; // detailed bullet points for the changelog
 | |
|   recommendedNextVersion: string; // the recommended next version of the project, x.x.x
 | |
| }
 | |
| 
 | |
| You are being given the files of the project. You should use them to create the commit message.
 | |
| Also you are given a diff
 | |
| 
 | |
| `,
 | |
|       messageHistory: [],
 | |
|       userMessage: contextString,
 | |
|     });
 | |
| 
 | |
|     // console.log(result.message);
 | |
|     const resultObject: INextCommitObject = JSON.parse(
 | |
|       result.message.replace('```json', '').replace('```', '')
 | |
|     );
 | |
| 
 | |
|     const previousChangelogPath = plugins.path.join(this.projectDir, 'changelog.md');
 | |
|     let previousChangelog: plugins.smartfile.SmartFile;
 | |
|     if (await plugins.smartfile.fs.fileExists(previousChangelogPath)) {
 | |
|       previousChangelog = await plugins.smartfile.SmartFile.fromFilePath(previousChangelogPath);
 | |
|     }
 | |
| 
 | |
|     if (!previousChangelog) {
 | |
|       // lets build the changelog based on that
 | |
|       const commitMessages = await gitRepo.getAllCommitMessages();
 | |
|       let result2 = await this.aiDocsRef.openaiInstance.chat({
 | |
|         messageHistory: [],
 | |
|         systemMessage: `
 | |
| You are building a changelog.md file for the project.
 | |
| Omit commits and versions that lack relevant changes.
 | |
| 
 | |
| A changelog entry should look like this:
 | |
| 
 | |
|     ## yyyy-mm-dd - x.x.x - scope here
 | |
|     main descriptiom here
 | |
|     - detailed bullet points follow
 | |
| 
 | |
| You are given:
 | |
| * the commit messages of the project
 | |
| 
 | |
| Only return the changelog file, so it can be written directly to changelog.md`,
 | |
|         userMessage: `
 | |
| Here are the commit messages:
 | |
| 
 | |
| ${JSON.stringify(commitMessages, null, 2)}
 | |
|   `,
 | |
|       });
 | |
| 
 | |
|       previousChangelog = await plugins.smartfile.SmartFile.fromString(
 | |
|         previousChangelogPath,
 | |
|         result2.message,
 | |
|         'utf8'
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     let oldChangelog = previousChangelog.contents.toString().replace('# Changelog\n\n', '');
 | |
|     let newDateString = new plugins.smarttime.ExtendedDate().exportToHyphedSortableDate();
 | |
|     let newChangelog = `# Changelog\n\n${`## ${newDateString} - {{nextVersion}} - {{nextVersionScope}}
 | |
| {{nextVersionMessage}}
 | |
| 
 | |
| {{nextVersionDetails}}
 | |
| `}\n\n${oldChangelog}\n`;
 | |
|     resultObject.changelog = newChangelog;
 | |
| 
 | |
|     return resultObject;
 | |
|   }
 | |
| }
 |