summaryrefslogtreecommitdiff
path: root/internal/cmd
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-10-31 20:13:32 +0200
committerPaul Buetow <paul@buetow.org>2025-10-31 20:13:32 +0200
commit11eea6a82cbfdde40ec1457c6ea080da4da6b7dc (patch)
tree8026068f6a3beb3ee02c45f06f4487f4b89caaf1 /internal/cmd
parent5c3e0b5cf99d028c4f06be7a825388b296e37a22 (diff)
feat: implement amp AI tool support and replace Taskfile with Magev0.10.0
- Add amp as default AI tool for release notes and showcase generation - Fallback chain: amp → hexai → claude → aichat - Replace Taskfile.yaml with magefile.go for build automation - Update all documentation (README.md, AGENTS.md, doc/development.md) - Update version to 0.10.0 Amp-Thread-ID: https://ampcode.com/threads/T-735ba1e2-0255-4b43-8ed1-6c0d2f78301b Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'internal/cmd')
-rw-r--r--internal/cmd/list.go4
-rw-r--r--internal/cmd/manage.go30
-rw-r--r--internal/cmd/release.go26
-rw-r--r--internal/cmd/root.go21
-rw-r--r--internal/cmd/showcase.go65
-rw-r--r--internal/cmd/sync.go58
-rw-r--r--internal/cmd/test.go12
7 files changed, 107 insertions, 109 deletions
diff --git a/internal/cmd/list.go b/internal/cmd/list.go
index 90d0eb8..31a39f5 100644
--- a/internal/cmd/list.go
+++ b/internal/cmd/list.go
@@ -3,8 +3,8 @@ package cmd
import (
"os"
- "github.com/spf13/cobra"
"codeberg.org/snonux/gitsyncer/internal/cli"
+ "github.com/spf13/cobra"
)
var listCmd = &cobra.Command{
@@ -37,4 +37,4 @@ func init() {
rootCmd.AddCommand(listCmd)
listCmd.AddCommand(listOrgsCmd)
listCmd.AddCommand(listReposCmd)
-} \ No newline at end of file
+}
diff --git a/internal/cmd/manage.go b/internal/cmd/manage.go
index 437bd96..6e2ffee 100644
--- a/internal/cmd/manage.go
+++ b/internal/cmd/manage.go
@@ -5,9 +5,9 @@ import (
"os"
"path/filepath"
- "github.com/spf13/cobra"
"codeberg.org/snonux/gitsyncer/internal/cli"
"codeberg.org/snonux/gitsyncer/internal/state"
+ "github.com/spf13/cobra"
)
var force bool
@@ -43,7 +43,7 @@ var cleanCmd = &cobra.Command{
flags := buildFlags()
flags.Clean = true
flags.Force = force
-
+
// TODO: Implement clean handler
fmt.Println("Clean command not yet implemented")
os.Exit(1)
@@ -64,7 +64,7 @@ This is designed for automated weekly synchronization from cron jobs or shell sc
flags := buildFlags()
flags.BatchRun = true
flags.Force = force
-
+
// Check state unless forced
if !force {
stateManager := state.NewManager(workDir)
@@ -72,23 +72,23 @@ This is designed for automated weekly synchronization from cron jobs or shell sc
if err != nil {
fmt.Fprintf(os.Stderr, "Warning: Failed to load state: %v\n", err)
}
-
+
if s.HasRunWithinWeek() {
- fmt.Printf("Batch run was already executed within the past week (last run: %s).\n",
+ fmt.Printf("Batch run was already executed within the past week (last run: %s).\n",
s.LastBatchRun.Format("2006-01-02 15:04:05"))
stateFile := filepath.Join(workDir, ".gitsyncer-state.json")
fmt.Printf("State file location: %s\n", stateFile)
fmt.Println("Skipping batch run. Use --force to override.")
os.Exit(0)
}
-
+
// Store state manager for later
flags.BatchRunStateManager = stateManager
flags.BatchRunState = s
}
-
+
fmt.Println("Starting weekly batch run (full sync + showcase)...")
-
+
// Enable full sync and showcase
flags.FullSync = true
flags.Showcase = true
@@ -96,24 +96,24 @@ This is designed for automated weekly synchronization from cron jobs or shell sc
flags.SyncGitHubPublic = true
flags.CreateGitHubRepos = true
flags.CreateCodebergRepos = true
-
+
// Run sync operations
exitCode := cli.HandleSyncCodebergPublic(cfg, flags)
if exitCode != 0 {
os.Exit(exitCode)
}
-
+
exitCode = cli.HandleSyncGitHubPublic(cfg, flags)
if exitCode != 0 {
os.Exit(exitCode)
}
-
+
// Run showcase
showcaseCode := cli.HandleShowcase(cfg, flags)
if showcaseCode != 0 {
os.Exit(showcaseCode)
}
-
+
// Save batch run state
if flags.BatchRunStateManager != nil && flags.BatchRunState != nil {
flags.BatchRunState.UpdateBatchRunTime()
@@ -125,7 +125,7 @@ This is designed for automated weekly synchronization from cron jobs or shell sc
fmt.Println("Next batch run allowed after one week.")
}
}
-
+
os.Exit(0)
},
}
@@ -135,8 +135,8 @@ func init() {
manageCmd.AddCommand(deleteRepoCmd)
manageCmd.AddCommand(cleanCmd)
manageCmd.AddCommand(batchRunCmd)
-
+
// Manage-specific flags
cleanCmd.Flags().BoolVarP(&force, "force", "f", false, "force operation without confirmation")
batchRunCmd.Flags().BoolVarP(&force, "force", "f", false, "force run even if already run this week")
-} \ No newline at end of file
+}
diff --git a/internal/cmd/release.go b/internal/cmd/release.go
index 9f4e713..656f4a6 100644
--- a/internal/cmd/release.go
+++ b/internal/cmd/release.go
@@ -3,8 +3,8 @@ package cmd
import (
"os"
- "github.com/spf13/cobra"
"codeberg.org/snonux/gitsyncer/internal/cli"
+ "github.com/spf13/cobra"
)
var (
@@ -16,11 +16,11 @@ var (
)
var releaseCmd = &cobra.Command{
- Use: "release",
- Short: "Manage releases across platforms",
- Long: `Check for version tags without releases and create them across
-GitHub and Codeberg. Supports AI-generated release notes via hexai (stdin pipeline),
-with fallback to Claude or aichat.`,
+ Use: "release",
+ Short: "Manage releases across platforms",
+ Long: `Check for version tags without releases and create them across
+GitHub and Codeberg. Supports AI-generated release notes via amp (stdin pipeline),
+with fallback to hexai, Claude, or aichat.`,
}
var releaseCheckCmd = &cobra.Command{
@@ -40,7 +40,7 @@ If no repository is specified, checks all configured repositories.`,
Run: func(cmd *cobra.Command, args []string) {
flags := buildFlags()
flags.CheckReleases = true
-
+
if len(args) > 0 {
// Check specific repo
exitCode := cli.HandleCheckReleasesForRepo(cfg, flags, args[0])
@@ -74,8 +74,8 @@ If no repository is specified, processes all configured repositories.`,
# Create for specific repository without AI
gitsyncer release create myproject --no-ai-notes
- # Use aichat instead of claude for AI release notes
- gitsyncer release create --ai-tool aichat`,
+ # Use amp for AI release notes
+gitsyncer release create --ai-tool amp`,
Run: func(cmd *cobra.Command, args []string) {
flags := buildFlags()
flags.CheckReleases = true
@@ -83,7 +83,7 @@ If no repository is specified, processes all configured repositories.`,
flags.AIReleaseNotes = !noAINotes
flags.UpdateReleases = updateExisting
flags.AITool = aiTool
-
+
if len(args) > 0 {
// Create releases for specific repo
exitCode := cli.HandleCheckReleasesForRepo(cfg, flags, args[0])
@@ -100,14 +100,14 @@ func init() {
rootCmd.AddCommand(releaseCmd)
releaseCmd.AddCommand(releaseCheckCmd)
releaseCmd.AddCommand(releaseCreateCmd)
-
+
// Release flags
releaseCmd.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "preview what releases would be created")
-
+
// Create-specific flags
releaseCreateCmd.Flags().BoolVar(&autoRelease, "auto", false, "skip confirmation prompts")
releaseCreateCmd.Flags().BoolVar(&noAINotes, "no-ai-notes", false, "disable AI-generated release notes (AI notes are enabled by default)")
releaseCreateCmd.Flags().BoolVar(&updateExisting, "update-existing", false, "update existing releases with new AI-generated notes")
releaseCreateCmd.Flags().StringVar(&templatePath, "template", "", "custom template for release notes")
- releaseCreateCmd.Flags().StringVar(&aiTool, "ai-tool", "claude", "AI tool to use for release notes (claude or aichat; hexai is tried first if available)")
+ releaseCreateCmd.Flags().StringVar(&aiTool, "ai-tool", "amp", "AI tool to use for release notes (amp, claude, aichat, or hexai; amp is tried first if available)")
}
diff --git a/internal/cmd/root.go b/internal/cmd/root.go
index bf4f64a..caf89f1 100644
--- a/internal/cmd/root.go
+++ b/internal/cmd/root.go
@@ -5,15 +5,15 @@ import (
"os"
"path/filepath"
- "github.com/spf13/cobra"
"codeberg.org/snonux/gitsyncer/internal/config"
"codeberg.org/snonux/gitsyncer/internal/version"
+ "github.com/spf13/cobra"
)
var (
- cfgFile string
- workDir string
- cfg *config.Config
+ cfgFile string
+ workDir string
+ cfg *config.Config
rootCmd = &cobra.Command{
Use: "gitsyncer",
Short: "Synchronize git repositories across multiple platforms",
@@ -25,7 +25,7 @@ keeps all branches in sync across different git hosting platforms.`,
if cmd.Use == "version" {
return
}
-
+
// Load configuration
var err error
cfg, err = config.Load(cfgFile)
@@ -35,7 +35,7 @@ keeps all branches in sync across different git hosting platforms.`,
fmt.Fprintf(os.Stderr, "See 'gitsyncer help' for more information.\n")
os.Exit(1)
}
-
+
// Use config WorkDir if no flag was explicitly provided
if !cmd.Flags().Changed("work-dir") && cfg.WorkDir != "" {
workDir = cfg.WorkDir
@@ -54,16 +54,16 @@ func Execute() {
func init() {
// Global flags
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "configuration file (default: ~/.config/gitsyncer/config.json)")
-
+
// Set default work directory
home, err := os.UserHomeDir()
defaultWorkDir := ".gitsyncer-work"
if err == nil {
defaultWorkDir = filepath.Join(home, "git", "gitsyncer-workdir")
}
-
+
rootCmd.PersistentFlags().StringVarP(&workDir, "work-dir", "w", defaultWorkDir, "working directory for operations")
-
+
// Version command
rootCmd.AddCommand(&cobra.Command{
Use: "version",
@@ -72,6 +72,5 @@ func init() {
fmt.Println(version.GetVersion())
},
})
-
-}
+}
diff --git a/internal/cmd/showcase.go b/internal/cmd/showcase.go
index 6f9f984..a590756 100644
--- a/internal/cmd/showcase.go
+++ b/internal/cmd/showcase.go
@@ -4,26 +4,25 @@ import (
"fmt"
"os"
- "github.com/spf13/cobra"
"codeberg.org/snonux/gitsyncer/internal/cli"
+ "github.com/spf13/cobra"
)
var (
- forceRegenerate bool
- outputPath string
- outputFormat string
- excludePattern string
- showcaseAITool string
- showcaseRepo string
+ forceRegenerate bool
+ outputPath string
+ outputFormat string
+ excludePattern string
+ showcaseAITool string
+ showcaseRepo string
)
var showcaseCmd = &cobra.Command{
Use: "showcase",
Short: "Generate AI-powered project showcase",
- Long: `Generate a comprehensive showcase of all your projects using AI.
+ Long: `Generate a comprehensive showcase of all your projects using AI.
This feature creates a formatted document with project summaries, statistics,
-and code snippets. By default uses Claude, but will try hexai first if available,
-and can also use aichat.`,
+and code snippets. By default uses amp, with fallback to hexai, claude, and aichat.`,
Example: ` # Generate showcase with cached summaries
gitsyncer showcase
@@ -40,30 +39,30 @@ and can also use aichat.`,
gitsyncer showcase --exclude "test-.*"
# Use a specific AI tool
- gitsyncer showcase --ai-tool hexai`,
- Run: func(cmd *cobra.Command, args []string) {
- flags := buildFlags()
- flags.Showcase = true
- flags.Force = forceRegenerate
- flags.AITool = showcaseAITool
- if showcaseRepo != "" {
- flags.SyncRepo = showcaseRepo
- }
-
- fmt.Println("Running showcase generation for all repositories...")
- exitCode := cli.HandleShowcaseOnly(cfg, flags)
- os.Exit(exitCode)
- },
+ gitsyncer showcase --ai-tool amp`,
+ Run: func(cmd *cobra.Command, args []string) {
+ flags := buildFlags()
+ flags.Showcase = true
+ flags.Force = forceRegenerate
+ flags.AITool = showcaseAITool
+ if showcaseRepo != "" {
+ flags.SyncRepo = showcaseRepo
+ }
+
+ fmt.Println("Running showcase generation for all repositories...")
+ exitCode := cli.HandleShowcaseOnly(cfg, flags)
+ os.Exit(exitCode)
+ },
}
func init() {
- rootCmd.AddCommand(showcaseCmd)
-
- // Showcase flags
- showcaseCmd.Flags().BoolVarP(&forceRegenerate, "force", "f", false, "force regeneration of cached summaries")
- showcaseCmd.Flags().StringVarP(&outputPath, "output", "o", "", "custom output path (default: ~/git/foo.zone-content/gemtext/about/showcase.gmi.tpl)")
- showcaseCmd.Flags().StringVar(&outputFormat, "format", "gemtext", "output format: gemtext, markdown, html")
- showcaseCmd.Flags().StringVar(&excludePattern, "exclude", "", "exclude repos matching pattern")
- showcaseCmd.Flags().StringVar(&showcaseAITool, "ai-tool", "claude", "AI tool for summaries: hexai, claude, claude-code, or aichat (default tries hexai→claude→aichat)")
- showcaseCmd.Flags().StringVar(&showcaseRepo, "repo", "", "only generate showcase for a single repository")
+ rootCmd.AddCommand(showcaseCmd)
+
+ // Showcase flags
+ showcaseCmd.Flags().BoolVarP(&forceRegenerate, "force", "f", false, "force regeneration of cached summaries")
+ showcaseCmd.Flags().StringVarP(&outputPath, "output", "o", "", "custom output path (default: ~/git/foo.zone-content/gemtext/about/showcase.gmi.tpl)")
+ showcaseCmd.Flags().StringVar(&outputFormat, "format", "gemtext", "output format: gemtext, markdown, html")
+ showcaseCmd.Flags().StringVar(&excludePattern, "exclude", "", "exclude repos matching pattern")
+ showcaseCmd.Flags().StringVar(&showcaseAITool, "ai-tool", "amp", "AI tool for summaries: amp, hexai, claude, claude-code, or aichat (default tries amp→hexai→claude→aichat)")
+ showcaseCmd.Flags().StringVar(&showcaseRepo, "repo", "", "only generate showcase for a single repository")
}
diff --git a/internal/cmd/sync.go b/internal/cmd/sync.go
index 86505d5..a28f50d 100644
--- a/internal/cmd/sync.go
+++ b/internal/cmd/sync.go
@@ -3,18 +3,18 @@ package cmd
import (
"os"
- "github.com/spf13/cobra"
"codeberg.org/snonux/gitsyncer/internal/cli"
+ "github.com/spf13/cobra"
)
var (
- dryRun bool
- backup bool
- createRepos bool
- noReleases bool
- autoCreate bool
+ dryRun bool
+ backup bool
+ createRepos bool
+ noReleases bool
+ autoCreate bool
noAIReleaseNotes bool
- syncAITool string
+ syncAITool string
)
var syncCmd = &cobra.Command{
@@ -42,12 +42,12 @@ var syncRepoCmd = &cobra.Command{
# Sync without AI-generated release notes
gitsyncer sync repo myproject --no-ai-release-notes
- # Auto-create releases using aichat for AI notes
- gitsyncer sync repo myproject --auto-create-releases --ai-tool aichat`,
+ # Auto-create releases using amp for AI notes
+gitsyncer sync repo myproject --auto-create-releases --ai-tool amp`,
Run: func(cmd *cobra.Command, args []string) {
flags := buildFlags()
flags.SyncRepo = args[0]
-
+
exitCode := cli.HandleSync(cfg, flags)
if exitCode == 0 && !noReleases {
cli.HandleCheckReleasesForRepo(cfg, flags, args[0])
@@ -71,7 +71,7 @@ var syncAllCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
flags := buildFlags()
flags.SyncAll = true
-
+
exitCode := cli.HandleSyncAll(cfg, flags)
if exitCode == 0 && !noReleases {
cli.HandleCheckReleases(cfg, flags)
@@ -95,11 +95,11 @@ var syncCodebergToGitHubCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
flags := buildFlags()
flags.SyncCodebergPublic = true
-
+
if createRepos || autoCreate {
flags.CreateGitHubRepos = true
}
-
+
exitCode := cli.HandleSyncCodebergPublic(cfg, flags)
if exitCode == 0 && !noReleases {
cli.HandleCheckReleases(cfg, flags)
@@ -123,11 +123,11 @@ var syncGitHubToCodebergCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
flags := buildFlags()
flags.SyncGitHubPublic = true
-
+
if createRepos || autoCreate {
flags.CreateCodebergRepos = true
}
-
+
exitCode := cli.HandleSyncGitHubPublic(cfg, flags)
if exitCode == 0 && !noReleases {
cli.HandleCheckReleases(cfg, flags)
@@ -156,13 +156,13 @@ repositories between GitHub and Codeberg. This is equivalent to the old --full f
flags.SyncGitHubPublic = true
flags.CreateGitHubRepos = true
flags.CreateCodebergRepos = true
-
+
// First sync Codeberg to GitHub
exitCode := cli.HandleSyncCodebergPublic(cfg, flags)
if exitCode != 0 {
os.Exit(exitCode)
}
-
+
// Then sync GitHub to Codeberg
exitCode = cli.HandleSyncGitHubPublic(cfg, flags)
if exitCode == 0 && !noReleases {
@@ -174,14 +174,14 @@ repositories between GitHub and Codeberg. This is equivalent to the old --full f
func init() {
rootCmd.AddCommand(syncCmd)
-
+
// Add subcommands
syncCmd.AddCommand(syncRepoCmd)
syncCmd.AddCommand(syncAllCmd)
syncCmd.AddCommand(syncCodebergToGitHubCmd)
syncCmd.AddCommand(syncGitHubToCodebergCmd)
syncCmd.AddCommand(syncBidirectionalCmd)
-
+
// Sync flags (available for all sync subcommands)
syncCmd.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "preview what would be synced")
syncCmd.PersistentFlags().BoolVar(&backup, "backup", false, "include backup locations")
@@ -189,20 +189,20 @@ func init() {
syncCmd.PersistentFlags().BoolVar(&noReleases, "no-releases", false, "skip release checking after sync")
syncCmd.PersistentFlags().BoolVar(&autoCreate, "auto-create-releases", false, "automatically create releases without confirmation")
syncCmd.PersistentFlags().BoolVar(&noAIReleaseNotes, "no-ai-release-notes", false, "disable AI-generated release notes (AI notes are enabled by default)")
- syncCmd.PersistentFlags().StringVar(&syncAITool, "ai-tool", "claude", "AI tool to use for release notes when auto-creating (claude or aichat; hexai is tried first if available)")
+ syncCmd.PersistentFlags().StringVar(&syncAITool, "ai-tool", "amp", "AI tool to use for release notes when auto-creating (amp, claude, aichat, or hexai; amp is tried first if available)")
}
func buildFlags() *cli.Flags {
return &cli.Flags{
- ConfigPath: cfgFile,
- WorkDir: workDir,
- DryRun: dryRun,
- Backup: backup,
- NoCheckReleases: noReleases,
- AutoCreateReleases: autoCreate,
- AIReleaseNotes: !noAIReleaseNotes,
- AITool: syncAITool,
- CreateGitHubRepos: createRepos,
+ ConfigPath: cfgFile,
+ WorkDir: workDir,
+ DryRun: dryRun,
+ Backup: backup,
+ NoCheckReleases: noReleases,
+ AutoCreateReleases: autoCreate,
+ AIReleaseNotes: !noAIReleaseNotes,
+ AITool: syncAITool,
+ CreateGitHubRepos: createRepos,
CreateCodebergRepos: createRepos,
}
}
diff --git a/internal/cmd/test.go b/internal/cmd/test.go
index 2c50112..ebee3db 100644
--- a/internal/cmd/test.go
+++ b/internal/cmd/test.go
@@ -4,9 +4,9 @@ import (
"fmt"
"os"
- "github.com/spf13/cobra"
"codeberg.org/snonux/gitsyncer/internal/cli"
"codeberg.org/snonux/gitsyncer/internal/config"
+ "github.com/spf13/cobra"
)
var testCmd = &cobra.Command{
@@ -52,11 +52,11 @@ var testConfigCmd = &cobra.Command{
fmt.Fprintf(os.Stderr, "Configuration validation failed: %v\n", err)
os.Exit(1)
}
-
+
fmt.Println("Configuration validation successful!")
fmt.Printf(" Organizations: %d\n", len(cfg.Organizations))
fmt.Printf(" Repositories: %d\n", len(cfg.Repositories))
-
+
// Check for common issues
hasGitHub := false
hasCodeberg := false
@@ -74,11 +74,11 @@ var testConfigCmd = &cobra.Command{
}
}
}
-
+
if !hasGitHub && !hasCodeberg {
fmt.Println(" ⚠️ Warning: No GitHub or Codeberg organizations configured")
}
-
+
os.Exit(0)
},
}
@@ -88,4 +88,4 @@ func init() {
testCmd.AddCommand(testGitHubCmd)
testCmd.AddCommand(testCodebergCmd)
testCmd.AddCommand(testConfigCmd)
-} \ No newline at end of file
+}