Pull-based GitOps-style Docker Compose deployer: polls a (private) Git repo, detects changed stacks and reconciles only the affected
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: remove dryRun, add branch selection

Signed-off-by: A. Ottr <alex@otter.foo>

A. Ottr 6a82bb84 7d870364

+42 -23
-8
README.md
··· 81 81 - Find changed stacks 82 82 - Deploy only changed stacks assigned to this host 83 83 84 - ### Dry Run 85 - 86 - To see what would be deployed without actually deploying: 87 - 88 - ```bash 89 - ./compose-sync -dry-run 90 - ``` 91 - 92 84 ### Custom Config Path 93 85 94 86 ```bash
+1
config.yml.example
··· 1 1 # Configuration file for compose-sync 2 2 repo_url: "git@github.com:user/compose-repo.git" # Optional: URL for cloning (not used if repo_path already exists) 3 3 repo_path: "/path/to/local/repo" # Required: Local path to the git repository 4 + branch: "main" # Optional: Git branch to sync (default: current branch or main) 4 5 concurrency: 3 # Optional: Number of concurrent deployments (default: 3) 5 6
+2 -11
main.go
··· 12 12 13 13 func main() { 14 14 configPath := flag.String("config", "config.yml", "Path to configuration file") 15 - dryRun := flag.Bool("dry-run", false, "Show what would be deployed without actually deploying") 16 15 flag.Parse() 17 16 18 17 cfg, err := loadConfig(*configPath) ··· 38 37 } 39 38 fmt.Printf("Detected host: %s\n", currentHost) 40 39 41 - fmt.Println("Pulling git repository...") 42 - changedStacks, err := pullAndDetectChanges(cfg.RepoPath) 40 + fmt.Printf("Pulling git repository (branch: %s)...\n", cfg.Branch) 41 + changedStacks, err := pullAndDetectChanges(cfg.RepoPath, cfg.Branch) 43 42 if err != nil { 44 43 log.Fatalf("Failed to pull or detect changes: %v", err) 45 44 } ··· 71 70 } 72 71 73 72 fmt.Printf("Stacks to deploy: %v\n", stacksToDeploy) 74 - 75 - if *dryRun { 76 - fmt.Println("DRY RUN: Would deploy the following stacks:") 77 - for _, stack := range stacksToDeploy { 78 - fmt.Printf(" - %s\n", stack) 79 - } 80 - return 81 - } 82 73 83 74 deployStacks(cfg.RepoPath, stacksToDeploy, cfg.Concurrency) 84 75 }
+39 -4
sync.go
··· 15 15 type config struct { 16 16 RepoURL string `yaml:"repo_url"` 17 17 RepoPath string `yaml:"repo_path"` 18 + Branch string `yaml:"branch"` 18 19 Concurrency int `yaml:"concurrency"` 19 20 } 20 21 ··· 31 32 32 33 if cfg.RepoPath == "" { 33 34 return nil, fmt.Errorf("repo_path is required in config") 35 + } 36 + 37 + if cfg.Branch == "" { 38 + cfg.Branch = detectCurrentBranch(cfg.RepoPath) 39 + if cfg.Branch == "" { 40 + cfg.Branch = "main" 41 + } 34 42 } 35 43 36 44 if cfg.Concurrency <= 0 { ··· 104 112 return stacks, nil 105 113 } 106 114 107 - func pullAndDetectChanges(repoPath string) ([]string, error) { 115 + func detectCurrentBranch(repoPath string) string { 116 + cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD") 117 + cmd.Dir = repoPath 118 + output, err := cmd.Output() 119 + if err != nil { 120 + return "" 121 + } 122 + return strings.TrimSpace(string(output)) 123 + } 124 + 125 + func pullAndDetectChanges(repoPath, branch string) ([]string, error) { 108 126 if _, err := os.Stat(repoPath); os.IsNotExist(err) { 109 127 return nil, fmt.Errorf("repository path does not exist: %s", repoPath) 110 128 } ··· 118 136 return nil, fmt.Errorf("failed to get previous HEAD: %w", err) 119 137 } 120 138 121 - if err := gitPull(repoPath); err != nil { 139 + if err := gitFetchPull(repoPath, branch); err != nil { 122 140 return nil, fmt.Errorf("failed to pull: %w", err) 123 141 } 124 142 ··· 140 158 return changedStacks, nil 141 159 } 142 160 143 - func gitPull(repoPath string) error { 144 - cmd := exec.Command("git", "pull") 161 + func gitFetchPull(repoPath, branch string) error { 162 + cmd := exec.Command("git", "fetch", "origin", branch) 163 + cmd.Dir = repoPath 164 + if err := cmd.Run(); err != nil { 165 + return fmt.Errorf("git fetch failed: %w", err) 166 + } 167 + 168 + cmd = exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD") 169 + cmd.Dir = repoPath 170 + currentBranch, _ := cmd.Output() 171 + if strings.TrimSpace(string(currentBranch)) != branch { 172 + cmd = exec.Command("git", "checkout", branch) 173 + cmd.Dir = repoPath 174 + if err := cmd.Run(); err != nil { 175 + return fmt.Errorf("git checkout failed: %w", err) 176 + } 177 + } 178 + 179 + cmd = exec.Command("git", "pull", "origin", branch) 145 180 cmd.Dir = repoPath 146 181 output, err := cmd.CombinedOutput() 147 182 if err != nil {