github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/git/v2/publisher.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package git
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/sirupsen/logrus"
    23  )
    24  
    25  // Publisher knows how to publish local work to a remote
    26  type Publisher interface {
    27  	// Commit stages all changes and commits them with the message
    28  	Commit(title, body string) error
    29  	// PushToFork pushes the local state to the fork remote
    30  	PushToFork(branch string, force bool) error
    31  	// PushToNamedFork is used for when the fork has a different name than the original repp
    32  	PushToNamedFork(forkName, branch string, force bool) error
    33  	// PushToCentral pushes the local state to the central remote
    34  	PushToCentral(branch string, force bool) error
    35  }
    36  
    37  // GitUserGetter fetches a name and email for us in git commits on-demand
    38  type GitUserGetter func() (name, email string, err error)
    39  
    40  type remotes struct {
    41  	publishRemote ForkRemoteResolver
    42  	centralRemote RemoteResolver
    43  }
    44  
    45  type publisher struct {
    46  	executor executor
    47  	remotes  remotes
    48  	info     GitUserGetter
    49  	logger   *logrus.Entry
    50  }
    51  
    52  // Commit adds all of the current content to the index and creates a commit
    53  func (p *publisher) Commit(title, body string) error {
    54  	p.logger.Infof("Committing changes with title %q", title)
    55  	name, email, err := p.info()
    56  	if err != nil {
    57  		return err
    58  	}
    59  	commands := [][]string{
    60  		{"add", "--all"},
    61  		{"commit", "--message", title, "--message", body, "--author", fmt.Sprintf("%s <%s>", name, email)},
    62  	}
    63  	for _, command := range commands {
    64  		if out, err := p.executor.Run(command...); err != nil {
    65  			return fmt.Errorf("error committing %q: %w %v", title, err, string(out))
    66  		}
    67  	}
    68  	return nil
    69  }
    70  
    71  func (p *publisher) PushToNamedFork(forkName, branch string, force bool) error {
    72  	remote, err := p.remotes.publishRemote(forkName)
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	args := []string{"push"}
    78  	if force {
    79  		args = append(args, "--force")
    80  	}
    81  	args = append(args, []string{remote, branch}...)
    82  
    83  	p.logger.Infof("Pushing branch %q to %q", branch, remote)
    84  	if out, err := p.executor.Run(args...); err != nil {
    85  		return fmt.Errorf("error pushing %q: %w %v", branch, err, string(out))
    86  	}
    87  	return nil
    88  }
    89  
    90  // PublishPush pushes the local state to the publish remote
    91  func (p *publisher) PushToFork(branch string, force bool) error {
    92  	return p.PushToNamedFork("", branch, force)
    93  }
    94  
    95  // CentralPush pushes the local state to the central remote
    96  func (p *publisher) PushToCentral(branch string, force bool) error {
    97  	remote, err := p.remotes.centralRemote()
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	args := []string{"push"}
   103  	if force {
   104  		args = append(args, "--force")
   105  	}
   106  	args = append(args, []string{remote, branch}...)
   107  
   108  	p.logger.Infof("Pushing branch %q to %q", branch, remote)
   109  	if out, err := p.executor.Run(args...); err != nil {
   110  		return fmt.Errorf("error pushing %q: %w %v", branch, err, string(out))
   111  	}
   112  	return nil
   113  }