feat: initial commit of Git Automation CLI

- Add comprehensive Git workflow automation tools
- Include branch management utilities
- Add commit helpers with conventional commit support
- Implement GitHub integration for PR management
- Add configuration management system
- Include comprehensive test coverage
- Add professional documentation and examples
This commit is contained in:
Dev
2025-09-11 17:02:12 +03:00
commit 15bbfdcda2
27 changed files with 5727 additions and 0 deletions

283
internal/cmd/commit.go Normal file
View File

@@ -0,0 +1,283 @@
package cmd
import (
"bufio"
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/iwasforcedtobehere/git-automation-cli/internal/git"
"github.com/iwasforcedtobehere/git-automation-cli/internal/validation"
)
var commitCmd = &cobra.Command{
Use: "commit",
Short: "Commit utilities",
Long: `Create and manage Git commits with templates and helpers.
Supports conventional commit format and commit message templates.`,
}
var commitCreateCmd = &cobra.Command{
Use: "create [message]",
Short: "Create a new commit",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
message := strings.Join(args, " ")
// Validate Git repository
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Validate commit message
if validationResult := validation.ValidateCommitMessage(message); !validationResult.IsValid {
return fmt.Errorf("invalid commit message: %s", validationResult.GetErrors())
}
// Check if working directory is clean
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Add all changes
if err := git.AddAll(ctx); err != nil {
return fmt.Errorf("failed to add changes: %w", err)
}
// Create commit
if err := git.Commit(ctx, message); err != nil {
return fmt.Errorf("failed to create commit: %w", err)
}
fmt.Printf("Created commit: %s\n", message)
return nil
},
}
var commitAmendCmd = &cobra.Command{
Use: "amend",
Short: "Amend the last commit",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
// Validate Git repository
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Check if working directory is clean
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Add all changes
if err := git.AddAll(ctx); err != nil {
return fmt.Errorf("failed to add changes: %w", err)
}
// Amend commit
var err error
_, err = git.Run(ctx, "commit", "--amend", "--no-edit")
if err != nil {
return fmt.Errorf("failed to amend commit: %w", err)
}
fmt.Println("Amended last commit")
return nil
},
}
var commitFixupCmd = &cobra.Command{
Use: "fixup [commit]",
Short: "Create a fixup commit",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
commit := args[0]
// Validate Git repository
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Check if working directory is clean
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Add all changes
if err := git.AddAll(ctx); err != nil {
return fmt.Errorf("failed to add changes: %w", err)
}
// Create fixup commit
var err error
_, err = git.Run(ctx, "commit", "--fixup", commit)
if err != nil {
return fmt.Errorf("failed to create fixup commit: %w", err)
}
fmt.Printf("Created fixup commit for %s\n", commit)
return nil
},
}
var commitConventionalCmd = &cobra.Command{
Use: "conventional",
Short: "Create a conventional commit",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
// Get commit type
fmt.Println("Select commit type:")
fmt.Println("1. feat: A new feature")
fmt.Println("2. fix: A bug fix")
fmt.Println("3. docs: Documentation only changes")
fmt.Println("4. style: Changes that do not affect the meaning of the code")
fmt.Println("5. refactor: A code change that neither fixes a bug nor adds a feature")
fmt.Println("6. perf: A code change that improves performance")
fmt.Println("7. test: Adding missing tests or correcting existing tests")
fmt.Println("8. build: Changes that affect the build system or external dependencies")
fmt.Println("9. ci: Changes to our CI configuration files and scripts")
fmt.Println("10. chore: Other changes that don't modify src or test files")
var choice int
fmt.Print("Enter choice (1-10): ")
fmt.Scanln(&choice)
var commitType string
switch choice {
case 1:
commitType = "feat"
case 2:
commitType = "fix"
case 3:
commitType = "docs"
case 4:
commitType = "style"
case 5:
commitType = "refactor"
case 6:
commitType = "perf"
case 7:
commitType = "test"
case 8:
commitType = "build"
case 9:
commitType = "ci"
case 10:
commitType = "chore"
default:
return fmt.Errorf("invalid choice")
}
// Get scope
fmt.Print("Enter scope (optional, press Enter to skip): ")
reader := bufio.NewReader(os.Stdin)
scope, _ := reader.ReadString('\n')
scope = strings.TrimSpace(scope)
// Get description
fmt.Print("Enter description: ")
description, _ := reader.ReadString('\n')
description = strings.TrimSpace(description)
if description == "" {
return fmt.Errorf("description is required")
}
// Get body (optional)
fmt.Print("Enter detailed description (optional, press Enter to skip): ")
body, _ := reader.ReadString('\n')
body = strings.TrimSpace(body)
// Build commit message
var message string
if scope != "" {
message = fmt.Sprintf("%s(%s): %s", commitType, scope, description)
} else {
message = fmt.Sprintf("%s: %s", commitType, description)
}
if body != "" {
message += "\n\n" + body
}
// Validate Git repository
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Validate conventional commit message
if validationResult := validation.ValidateConventionalCommit(message); !validationResult.IsValid {
return fmt.Errorf("invalid conventional commit message: %s", validationResult.GetErrors())
}
// Check if working directory is clean
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Add all changes
if err := git.AddAll(ctx); err != nil {
return fmt.Errorf("failed to add changes: %w", err)
}
// Create commit
if err := git.Commit(ctx, message); err != nil {
return fmt.Errorf("failed to create commit: %w", err)
}
fmt.Printf("Created conventional commit: %s\n", message)
return nil
},
}
var commitSignoffCmd = &cobra.Command{
Use: "signoff [message]",
Short: "Create a commit with sign-off",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
message := strings.Join(args, " ")
// Validate Git repository
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Validate commit message
if validationResult := validation.ValidateCommitMessage(message); !validationResult.IsValid {
return fmt.Errorf("invalid commit message: %s", validationResult.GetErrors())
}
// Check if working directory is clean
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
return fmt.Errorf(validationResult.GetErrors())
}
// Add all changes
if err := git.AddAll(ctx); err != nil {
return fmt.Errorf("failed to add changes: %w", err)
}
// Create commit with sign-off
var err error
_, err = git.Run(ctx, "commit", "-s", "-m", message)
if err != nil {
return fmt.Errorf("failed to create commit: %w", err)
}
fmt.Printf("Created signed-off commit: %s\n", message)
return nil
},
}
func init() {
rootCmd.AddCommand(commitCmd)
commitCmd.AddCommand(commitCreateCmd)
commitCmd.AddCommand(commitAmendCmd)
commitCmd.AddCommand(commitFixupCmd)
commitCmd.AddCommand(commitConventionalCmd)
commitCmd.AddCommand(commitSignoffCmd)
}