summaryrefslogtreecommitdiff
path: root/internal/sync/git_operations.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-07-22 09:54:49 +0300
committerPaul Buetow <paul@buetow.org>2026-07-22 09:54:49 +0300
commitea3b3b2ffc4a1d3c335994e22056a957cd962d21 (patch)
tree601aecf10b5d4a4721e895698d64e97b47561b5f /internal/sync/git_operations.go
parent813077134132a62d0c9c73c7020ed734ff9add0b (diff)
feat(sync): make backup fail-fast per-destination and add forcePush/descriptionSync creation support
Backup failures now disable retries only for the failing remote instead of the whole session, add an opt-in forcePush flag for backup organizations, and allow repository creation to go through descriptionSyncHost/Root when configured so the git remote endpoint can stay restricted. Also fixes the AI release-notes cache being bypassed by --force, which is meant to control sync scheduling, not cache invalidation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'internal/sync/git_operations.go')
-rw-r--r--internal/sync/git_operations.go38
1 files changed, 31 insertions, 7 deletions
diff --git a/internal/sync/git_operations.go b/internal/sync/git_operations.go
index e5c68d9..ef41731 100644
--- a/internal/sync/git_operations.go
+++ b/internal/sync/git_operations.go
@@ -268,9 +268,9 @@ func getAllUniqueBranches(output []byte) []string {
return branches
}
-// createSSHBareRepository creates a bare repository on an SSH server
-func createSSHBareRepository(sshHost, repoPath string) error {
- userHost, sshArgs, basePath, err := parseSSHLocation(sshHost)
+// createSSHBareRepository creates a bare repository on an SSH server.
+func createSSHBareRepository(org *config.Organization, repoPath string) error {
+ userHost, sshArgs, basePath, err := repositoryCreationLocation(org)
if err != nil {
return err
}
@@ -293,6 +293,18 @@ func createSSHBareRepository(sshHost, repoPath string) error {
return nil
}
+func repositoryCreationLocation(org *config.Organization) (string, []string, string, error) {
+ if org == nil {
+ return "", nil, "", fmt.Errorf("backup organization is required")
+ }
+
+ if org.DescriptionSyncHost != "" && org.DescriptionSyncRoot != "" {
+ return org.DescriptionSyncHost, []string{org.DescriptionSyncHost}, org.DescriptionSyncRoot, nil
+ }
+
+ return parseSSHLocation(org.Host)
+}
+
func parseSSHLocation(sshHost string) (string, []string, string, error) {
if strings.HasPrefix(sshHost, "ssh://") {
parsed, err := url.Parse(sshHost)
@@ -330,7 +342,7 @@ func parseSSHLocation(sshHost string) (string, []string, string, error) {
// pushBranchWithBackupSupport pushes a branch to a remote, creating SSH repos if needed
func pushBranchWithBackupSupport(repoPath, remoteName, branch string, remoteHasBranch bool, org *config.Organization) error {
- cmd := gitCommand(repoPath, "push", remoteName, branch, "--tags")
+ cmd := gitCommand(repoPath, pushBranchArgs(remoteName, branch, false, org)...)
output, err := cmd.CombinedOutput()
if err != nil {
@@ -352,12 +364,12 @@ func pushBranchWithBackupSupport(repoPath, remoteName, branch string, remoteHasB
}
// Create the bare repository
- if err := createSSHBareRepository(org.Host, repoName); err != nil {
+ if err := createSSHBareRepository(org, repoName); err != nil {
return fmt.Errorf("failed to create SSH repository: %w", err)
}
// Try pushing again
- cmd = gitCommand(repoPath, "push", remoteName, branch, "--tags")
+ cmd = gitCommand(repoPath, pushBranchArgs(remoteName, branch, false, org)...)
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to push after creating repository: %w", err)
}
@@ -374,7 +386,7 @@ func pushBranchWithBackupSupport(repoPath, remoteName, branch string, remoteHasB
if isBranchMissing(outputStr) {
fmt.Printf(" Creating new branch on %s\n", remoteName)
// Try again with -u flag to set upstream
- cmd = gitCommand(repoPath, "push", "-u", remoteName, branch, "--tags")
+ cmd = gitCommand(repoPath, pushBranchArgs(remoteName, branch, true, org)...)
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to push to %s: %w", remoteName, err)
}
@@ -391,6 +403,18 @@ func pushBranchWithBackupSupport(repoPath, remoteName, branch string, remoteHasB
return nil
}
+func pushBranchArgs(remoteName, branch string, setUpstream bool, org *config.Organization) []string {
+ args := []string{"push"}
+ if setUpstream {
+ args = append(args, "-u")
+ }
+ args = append(args, remoteName, branch, "--tags")
+ if org != nil && org.BackupLocation && org.ForcePush {
+ args = append(args, "--force")
+ }
+ return args
+}
+
// getRemoteURL gets the URL for a given remote
func getRemoteURL(repoPath, remoteName string) (string, error) {
cmd := gitCommand(repoPath, "remote", "get-url", remoteName)