package main import ( "fmt" "log" "os" "github.com/go-git/go-git/v5" . "github.com/go-git/go-git/v5/_examples" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing/object" "github.com/go-git/go-git/v5/plumbing/transport/ssh" ) // Example of how create a tag and push it to a remote. func main() { CheckArgs("", "", "", "", "", "") url := os.Args[1] directory := os.Args[2] tag := os.Args[3] key := os.Args[6] r, err := cloneRepo(url, directory, key) if err != nil { log.Printf("clone repo error: %s", err) return } created, err := setTag(r, tag) if err != nil { log.Printf("create tag error: %s", err) return } if created { err = pushTags(r, key) if err != nil { log.Printf("push tag error: %s", err) return } } } func cloneRepo(url, dir, publicKeyPath string) (*git.Repository, error) { log.Printf("cloning %s into %s", url, dir) auth, keyErr := publicKey(publicKeyPath) if keyErr != nil { return nil, keyErr } Info("git clone %s", url) r, err := git.PlainClone(dir, false, &git.CloneOptions{ Progress: os.Stdout, URL: url, Auth: auth, }) if err != nil { log.Printf("clone git repo error: %s", err) return nil, err } return r, nil } func publicKey(filePath string) (*ssh.PublicKeys, error) { var publicKey *ssh.PublicKeys sshKey, _ := os.ReadFile(filePath) publicKey, err := ssh.NewPublicKeys("git", []byte(sshKey), "") if err != nil { return nil, err } return publicKey, err } func tagExists(tag string, r *git.Repository) bool { tagFoundErr := "tag was found" Info("git show-ref --tag") tags, err := r.TagObjects() if err != nil { log.Printf("get tags error: %s", err) return false } res := false err = tags.ForEach(func(t *object.Tag) error { if t.Name == tag { res = true return fmt.Errorf(tagFoundErr) } return nil }) if err != nil && err.Error() != tagFoundErr { log.Printf("iterate tags error: %s", err) return false } return res } func setTag(r *git.Repository, tag string) (bool, error) { if tagExists(tag, r) { log.Printf("tag %s already exists", tag) return false, nil } log.Printf("Set tag %s", tag) h, err := r.Head() if err != nil { log.Printf("get HEAD error: %s", err) return false, err } Info("git tag -a %s %s -m \"%s\"", tag, h.Hash(), tag) _, err = r.CreateTag(tag, h.Hash(), &git.CreateTagOptions{ Message: tag, }) if err != nil { log.Printf("create tag error: %s", err) return false, err } return true, nil } func pushTags(r *git.Repository, publicKeyPath string) error { auth, _ := publicKey(publicKeyPath) po := &git.PushOptions{ RemoteName: "origin", Progress: os.Stdout, RefSpecs: []config.RefSpec{config.RefSpec("refs/tags/*:refs/tags/*")}, Auth: auth, } Info("git push --tags") err := r.Push(po) if err != nil { if err == git.NoErrAlreadyUpToDate { log.Print("origin remote was up to date, no push done") return nil } log.Printf("push to remote origin error: %s", err) return err } return nil }