Skip to content

fix(reconcile): made cross repo more robust #47

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 6 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions cmd/coco/commands/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,27 @@ func newReconcile() *cobra.Command {
},
}

c.PersistentFlags().StringVarP(&sourceBranch, "source", "s", "", "The souce branch to reconcile from.")
c.PersistentFlags().StringVarP(&sourceBranch, "source", "s", "", "The source branch to reconcile from.")
failOnError(c.MarkPersistentFlagRequired("source"), "reconcile")

c.PersistentFlags().StringVar(&sourceRemote, "source-remote", "origin", "The remote for the source branch.")
c.PersistentFlags().StringVar(&sourceRemote, "source-remote", "origin", `The URL for the source branch.
Can be left out incase the source and target branches are in the same repository.`)

c.PersistentFlags().StringVarP(&targetBranch, "target", "t", "", "The target branch to reconcile to.")
failOnError(c.MarkPersistentFlagRequired("target"), "reconcile")

c.PersistentFlags().StringVar(&targetRemote, "target-remote", "origin", "The remote for the target branch.")
c.PersistentFlags().StringVar(&targetRemote, "target-remote", "origin", `The URL for the target branch.
Can be left out incase the source and target branches are in the same repository.`)

c.PersistentFlags().StringVar(&repositoryName, "repo", "", "The name of the gihtub repository.")
c.PersistentFlags().StringVar(&repositoryName, "repo", "", "The name of the TARGET github repository.")
failOnError(
c.PersistentFlags().MarkDeprecated("repo", `please use "repository" flag instead.`),
"reconcile",
)
c.PersistentFlags().StringVar(&repositoryName, "repository", "", "The name of the gihtub repository.")
c.PersistentFlags().StringVar(&repositoryName, "repository", "", "The name of the TARGET github repository.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you not need the repository of the source branch at all?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. It should always be the repository of the target branch. In the case where the branches belong to different repositories, it will be automatically handled by the remotes we provide.

failOnError(c.MarkPersistentFlagRequired("repository"), "reconcile")

c.PersistentFlags().StringVar(&owner, "owner", "", "The account owner of the github repository.")
c.PersistentFlags().StringVar(&owner, "owner", "", "The account owner of the TARGET github repository.")
failOnError(c.MarkPersistentFlagRequired("owner"), "reconcile")

c.Flags().BoolVar(
Expand Down
16 changes: 12 additions & 4 deletions cmd/coco/reconcile/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func New(
if err := differentRemotes(targetBranch, sourceBranch, token, logger); err != nil {
return nil, err
}
reconcileBranchName = fmt.Sprintf("reconcile/remote-replica/%s-%s", sourceBranch.Name, targetBranch.Name)
}

client, err := githubClient(ctx, token, owner, repo, githubBaseURL, isEnterprise)
Expand All @@ -80,7 +81,8 @@ func New(

func (r *Client) Reconcile(force bool) error {
if r.target.Remote != r.source.Remote {
return nil
// change source.name to remote-replica/source.Name and continue
r.source.Name = fmt.Sprintf("remote-replica/%s", r.source.Name)
}
return r.merge(force)
}
Expand Down Expand Up @@ -140,7 +142,7 @@ func differentRemotes(targetBranch, sourceBranch BranchConfig, token string, log
if err == git.NoErrAlreadyUpToDate {
logger.Debugf("Target branch is already up to date")
} else if err != nil {
return err
return fmt.Errorf("target pull failed: %w", err)
}

// If the remotes are different, add the remote repository of the 'source' branch
Expand Down Expand Up @@ -171,6 +173,7 @@ func copyBranch(targetRepo *git.Repository, sourceBranch BranchConfig, remoteNam
if err != nil {
return err
}

err = refs.ForEach(func(ref *plumbing.Reference) error {
if ref.Name() == plumbing.ReferenceName(fmt.Sprintf("refs/remotes/%s/%s", remoteName, sourceBranch.Name)) {
sourceRef = ref
Expand All @@ -181,15 +184,20 @@ func copyBranch(targetRepo *git.Repository, sourceBranch BranchConfig, remoteNam
return err
}
ref := plumbing.NewHashReference(replicaBranchName, sourceRef.Hash())
if err := targetRepo.Storer.SetReference(ref); err != nil {
err = targetRepo.Storer.SetReference(ref)
if err != nil {
return err
}
return gitPush(targetRepo, &git.PushOptions{
err = gitPush(targetRepo, &git.PushOptions{
RemoteName: "origin",
Auth: &githttp.BasicAuth{Username: notUsed, Password: token},
Progress: os.Stdout,
Force: true,
})
if err == git.NoErrAlreadyUpToDate {
return nil
}
return err
}

func (r *Client) merge(force bool) error {
Expand Down