Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save IAmSurajBobade/f687c3a0a0dfec2f692fcd76651e2d3f to your computer and use it in GitHub Desktop.
Save IAmSurajBobade/f687c3a0a0dfec2f692fcd76651e2d3f to your computer and use it in GitHub Desktop.
Multi repo git
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"strings"
"time"
)
type Repository struct {
Path string
Name string
UtilsModule string
}
type Command struct {
Name string
Args []string
}
func main() {
repoPaths := flag.String("repos", "", "Comma-separated list of repository paths")
utilsModule := flag.String("utils", "", "Common utils module path (e.g., github.com/org/common-utils)")
dryRun := flag.Bool("dry-run", false, "Perform a dry run without making changes")
flag.Parse()
if *repoPaths == "" || *utilsModule == "" {
fmt.Println("Error: -repos and -utils flags are required")
flag.Usage()
os.Exit(1)
}
paths := strings.Split(*repoPaths, ",")
var repos []Repository
for i, path := range paths {
repoName := fmt.Sprintf("repo%d", i+1)
if strings.Contains(path, "/") {
parts := strings.Split(strings.TrimSpace(path), "/")
repoName = parts[len(parts)-1]
}
repos = append(repos, Repository{
Path: strings.TrimSpace(path),
Name: repoName,
UtilsModule: *utilsModule,
})
}
stashName := fmt.Sprintf("auto-update-utils-%s", time.Now().Format("20060102-150405"))
for _, repo := range repos {
err := processRepository(repo, stashName, *dryRun)
if err != nil {
fmt.Printf("Error processing %s: %v\n", repo.Name, err)
continue
}
fmt.Printf("Successfully processed %s\n", repo.Name)
}
}
func processRepository(repo Repository, stashName string, dryRun bool) error {
if err := os.Chdir(repo.Path); err != nil {
return fmt.Errorf("failed to change directory: %v", err)
}
branchName := fmt.Sprintf("update-utils-%s", time.Now().Format("20060102"))
prTitle := "Update common-utils version"
prBody := fmt.Sprintf(`# Update Common Utils
This PR updates the %s module to the latest version.
Changes:
- Updated go.mod to use latest %s
- Ran go mod tidy
- All tests passing
Automated update performed on: %s`, repo.UtilsModule, repo.UtilsModule, time.Now().Format(time.RFC1123))
commands := []Command{
{Name: "git", Args: []string{"stash", "push", "-m", stashName}},
{Name: "git", Args: []string{"checkout", "-b", branchName}},
{Name: "go", Args: []string{"get", "-u", repo.UtilsModule}},
{Name: "go", Args: []string{"mod", "tidy"}},
{Name: "go", Args: []string{"test", "./..."}},
{Name: "git", Args: []string{"add", "go.mod", "go.sum"}},
{Name: "git", Args: []string{"commit", "-m", "Update common utils version"}},
{Name: "git", Args: []string{"push", "origin", branchName}},
{Name: "gh", Args: []string{"pr", "create", "--title", prTitle, "--body", prBody, "--base", "main", "--head", branchName}},
{Name: "git", Args: []string{"checkout", "main"}},
{Name: "git", Args: []string{"stash", "apply", fmt.Sprintf("stash^{/%s}", stashName)}},
}
if dryRun {
fmt.Printf("[DRY RUN] Would process repository %s:\n", repo.Name)
for _, cmd := range commands {
fmt.Printf("- %s %s\n", cmd.Name, strings.Join(cmd.Args, " "))
}
return nil
}
for _, cmd := range commands {
if err := execCommand(cmd); err != nil {
return fmt.Errorf("failed to execute %s %s: %v", cmd.Name, strings.Join(cmd.Args, " "), err)
}
}
return nil
}
func execCommand(cmd Command) error {
command := exec.Command(cmd.Name, cmd.Args...)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
return command.Run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment