forked from toolshed/abra
		
	| @ -4,6 +4,7 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
| 	"path" | 	"path" | ||||||
| 	"slices" | 	"slices" | ||||||
|  |  | ||||||
| @ -56,9 +57,17 @@ It is quite easy to get rate limited by Docker Hub when running this command. | |||||||
| If you have a Hub account you can "docker login" and Abra will automatically | If you have a Hub account you can "docker login" and Abra will automatically | ||||||
| use those details. | use those details. | ||||||
|  |  | ||||||
| Push your new release to git.coopcloud.tech with "--publish/-p". This requires | Publish your new release to git.coopcloud.tech with "--publish/-p". This | ||||||
| that you have permission to git push to these repositories and have your SSH | requires that you have permission to git push to these repositories and have | ||||||
| keys configured on your account.`), | your SSH keys configured on your account. Enable ssh-agent and make sure to add | ||||||
|  | your private key and enter your passphrase beforehand. | ||||||
|  |  | ||||||
|  |     eval ` + "`ssh-agent`" + ` | ||||||
|  |     ssh-add ~/.ssh/<my-ssh-private-key-for-git-coopcloud-tech>`), | ||||||
|  | 	Example: `  # publish catalogue | ||||||
|  |   eval ` + "`ssh-agent`" + ` | ||||||
|  |   ssh-add ~/.ssh/id_ed25519 | ||||||
|  |   abra catalogue generate -p`, | ||||||
| 	Args: cobra.RangeArgs(0, 1), | 	Args: cobra.RangeArgs(0, 1), | ||||||
| 	ValidArgsFunction: func( | 	ValidArgsFunction: func( | ||||||
| 		cmd *cobra.Command, | 		cmd *cobra.Command, | ||||||
| @ -72,6 +81,10 @@ keys configured on your account.`), | |||||||
| 			recipeName = args[0] | 			recipeName = args[0] | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if os.Getenv("SSH_AUTH_SOCK") == "" { | ||||||
|  | 			log.Warn(i18n.G("ssh: SSH_AUTH_SOCK missing, --publish/-p will fail. see \"abra catalogue generate --help\"")) | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if recipeName != "" { | 		if recipeName != "" { | ||||||
| 			internal.ValidateRecipe(args, cmd.Name()) | 			internal.ValidateRecipe(args, cmd.Name()) | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ import ( | |||||||
| 	"github.com/AlecAivazis/survey/v2" | 	"github.com/AlecAivazis/survey/v2" | ||||||
| 	"github.com/distribution/reference" | 	"github.com/distribution/reference" | ||||||
| 	"github.com/go-git/go-git/v5" | 	"github.com/go-git/go-git/v5" | ||||||
|  | 	"github.com/go-git/go-git/v5/plumbing" | ||||||
| 	"github.com/spf13/cobra" | 	"github.com/spf13/cobra" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @ -45,7 +46,15 @@ major and therefore require intervention while doing the upgrade work. | |||||||
|  |  | ||||||
| Publish your new release to git.coopcloud.tech with "--publish/-p". This | Publish your new release to git.coopcloud.tech with "--publish/-p". This | ||||||
| requires that you have permission to git push to these repositories and have | requires that you have permission to git push to these repositories and have | ||||||
| your SSH keys configured on your account.`), | your SSH keys configured on your account. Enable ssh-agent and make sure to add | ||||||
|  | your private key and enter your passphrase beforehand. | ||||||
|  |  | ||||||
|  |     eval ` + "`ssh-agent`" + ` | ||||||
|  |     ssh-add ~/.ssh/<my-ssh-private-key-for-git-coopcloud-tech>`), | ||||||
|  | 	Example: `  # publish release | ||||||
|  |   eval ` + "`ssh-agent`" + ` | ||||||
|  |   ssh-add ~/.ssh/id_ed25519 | ||||||
|  |   abra recipe release gitea -p`, | ||||||
| 	Args: cobra.RangeArgs(1, 2), | 	Args: cobra.RangeArgs(1, 2), | ||||||
| 	ValidArgsFunction: func( | 	ValidArgsFunction: func( | ||||||
| 		cmd *cobra.Command, | 		cmd *cobra.Command, | ||||||
| @ -93,8 +102,24 @@ your SSH keys configured on your account.`), | |||||||
| 			log.Fatal(i18n.G("cannot specify tag and bump type at the same time")) | 			log.Fatal(i18n.G("cannot specify tag and bump type at the same time")) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		repo, err := git.PlainOpen(recipe.Dir) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		preCommitHead, err := repo.Head() | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if tagString != "" { | 		if tagString != "" { | ||||||
| 			if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { | 			if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { | ||||||
|  | 				if cleanErr := cleanTag(recipe, tagString); cleanErr != nil { | ||||||
|  | 					log.Fatal(cleanErr) | ||||||
|  | 				} | ||||||
|  | 				if cleanErr := cleanCommit(recipe, preCommitHead); cleanErr != nil { | ||||||
|  | 					log.Fatal(cleanErr) | ||||||
|  | 				} | ||||||
| 				log.Fatal(err) | 				log.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -125,16 +150,25 @@ your SSH keys configured on your account.`), | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if len(tags) > 0 { | 		if len(tags) > 0 { | ||||||
| 			log.Warn(i18n.G("previous git tags detected, assuming this is a new semver release")) | 			log.Warn(i18n.G("previous git tags detected, assuming new semver release")) | ||||||
| 			if err := createReleaseFromPreviousTag(tagString, mainAppVersion, recipe, tags); err != nil { | 			if err := createReleaseFromPreviousTag(tagString, mainAppVersion, recipe, tags); err != nil { | ||||||
|  | 				if cleanErr := cleanTag(recipe, tagString); cleanErr != nil { | ||||||
|  | 					log.Fatal(cleanErr) | ||||||
|  | 				} | ||||||
|  | 				if cleanErr := cleanCommit(recipe, preCommitHead); cleanErr != nil { | ||||||
|  | 					log.Fatal(cleanErr) | ||||||
|  | 				} | ||||||
| 				log.Fatal(err) | 				log.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			log.Warn(i18n.G("no tag specified and no previous tag available for %s, assuming this is the initial release", recipe.Name)) | 			log.Warn(i18n.G("no tag specified and no previous tag available for %s, assuming initial release", recipe.Name)) | ||||||
|  |  | ||||||
| 			if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { | 			if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { | ||||||
| 				if cleanUpErr := cleanUpTag(recipe, tagString); err != nil { | 				if cleanErr := cleanTag(recipe, tagString); cleanErr != nil { | ||||||
| 					log.Fatal(cleanUpErr) | 					log.Fatal(cleanErr) | ||||||
|  | 				} | ||||||
|  | 				if cleanErr := cleanCommit(recipe, preCommitHead); cleanErr != nil { | ||||||
|  | 					log.Fatal(cleanErr) | ||||||
| 				} | 				} | ||||||
| 				log.Fatal(err) | 				log.Fatal(err) | ||||||
| 			} | 			} | ||||||
| @ -217,19 +251,19 @@ func createReleaseFromTag(recipe recipe.Recipe, tagString, mainAppVersion string | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := addReleaseNotes(recipe, tagString); err != nil { | 	if err := addReleaseNotes(recipe, tagString); err != nil { | ||||||
| 		log.Fatal(err) | 		return errors.New(i18n.G("failed to add release notes: %s", err.Error())) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := commitRelease(recipe, tagString); err != nil { | 	if err := commitRelease(recipe, tagString); err != nil { | ||||||
| 		log.Fatal(err) | 		return errors.New(i18n.G("failed to commit changes: %s", err.Error())) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := tagRelease(tagString, repo); err != nil { | 	if err := tagRelease(tagString, repo); err != nil { | ||||||
| 		log.Fatal(err) | 		return errors.New(i18n.G("failed to tag release: %s", err.Error())) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := pushRelease(recipe, tagString); err != nil { | 	if err := pushRelease(recipe, tagString); err != nil { | ||||||
| 		log.Fatal(err) | 		return errors.New(i18n.G("failed to publish new release: %s", err.Error())) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| @ -314,7 +348,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	prompt := &survey.Input{ | 	prompt := &survey.Input{ | ||||||
| 		Message: i18n.G("Release Note (leave empty for no release note)"), | 		Message: i18n.G("add release note? (leave empty to skip)"), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var releaseNote string | 	var releaseNote string | ||||||
| @ -406,9 +440,14 @@ func pushRelease(recipe recipe.Recipe, tagString string) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if publish { | 	if publish { | ||||||
|  | 		if os.Getenv("SSH_AUTH_SOCK") == "" { | ||||||
|  | 			return errors.New(i18n.G("ssh-agent not found. see \"abra recipe release --help\" and try again")) | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if err := recipe.Push(internal.Dry); err != nil { | 		if err := recipe.Push(internal.Dry); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		url := fmt.Sprintf("%s/src/tag/%s", recipe.GitURL, tagString) | 		url := fmt.Sprintf("%s/src/tag/%s", recipe.GitURL, tagString) | ||||||
| 		log.Info(i18n.G("new release published: %s", url)) | 		log.Info(i18n.G("new release published: %s", url)) | ||||||
| 	} else { | 	} else { | ||||||
| @ -484,7 +523,7 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if lastGitTag.String() == tagString { | 	if lastGitTag.String() == tagString { | ||||||
| 		log.Fatal(i18n.G("latest git tag (%s) and synced label (%s) are the same?", lastGitTag, tagString)) | 		return errors.New(i18n.G("latest git tag (%s) and synced label (%s) are the same?", lastGitTag, tagString)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !internal.NoInput { | 	if !internal.NoInput { | ||||||
| @ -494,43 +533,66 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip | |||||||
|  |  | ||||||
| 		var ok bool | 		var ok bool | ||||||
| 		if err := survey.AskOne(prompt, &ok); err != nil { | 		if err := survey.AskOne(prompt, &ok); err != nil { | ||||||
| 			log.Fatal(err) | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			log.Fatal(i18n.G("exiting as requested")) | 			return errors.New(i18n.G("exiting as requested")) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := addReleaseNotes(recipe, tagString); err != nil { | 	if err := addReleaseNotes(recipe, tagString); err != nil { | ||||||
| 		log.Fatal(err) | 		return errors.New(i18n.G("failed to add release notes: %s", err.Error())) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := commitRelease(recipe, tagString); err != nil { | 	if err := commitRelease(recipe, tagString); err != nil { | ||||||
| 		log.Fatal(i18n.G("failed to commit changes: %s", err.Error())) | 		return errors.New(i18n.G("failed to commit changes: %s", err.Error())) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := tagRelease(tagString, repo); err != nil { | 	if err := tagRelease(tagString, repo); err != nil { | ||||||
| 		log.Fatal(i18n.G("failed to tag release: %s", err.Error())) | 		return errors.New(i18n.G("failed to tag release: %s", err.Error())) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := pushRelease(recipe, tagString); err != nil { | 	if err := pushRelease(recipe, tagString); err != nil { | ||||||
| 		log.Fatal(i18n.G("failed to publish new release: %s", err.Error())) | 		return errors.New(i18n.G("failed to publish new release: %s", err.Error())) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // cleanUpTag removes a freshly created tag | // cleanCommit soft removes the latest release commit. No change are lost the | ||||||
| func cleanUpTag(recipe recipe.Recipe, tag string) error { | // the commit itself is removed. This is the equivalent of `git reset HEAD~1`. | ||||||
|  | func cleanCommit(recipe recipe.Recipe, head *plumbing.Reference) error { | ||||||
| 	repo, err := git.PlainOpen(recipe.Dir) | 	repo, err := git.PlainOpen(recipe.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return errors.New(i18n.G("unable to open repo in %s: %s", recipe.Dir, err)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	worktree, err := repo.Worktree() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.New(i18n.G("unable to open work tree in %s: %s", recipe.Dir, err)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	opts := &git.ResetOptions{Commit: head.Hash(), Mode: git.MixedReset} | ||||||
|  | 	if err := worktree.Reset(opts); err != nil { | ||||||
|  | 		return errors.New(i18n.G("unable to soft reset %s: %s", recipe.Dir, err)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	log.Debug(i18n.G("removed freshly created commit")) | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // cleanTag removes a freshly created tag | ||||||
|  | func cleanTag(recipe recipe.Recipe, tag string) error { | ||||||
|  | 	repo, err := git.PlainOpen(recipe.Dir) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return errors.New(i18n.G("unable to open repo in %s: %s", recipe.Dir, err)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := repo.DeleteTag(tag); err != nil { | 	if err := repo.DeleteTag(tag); err != nil { | ||||||
| 		if !strings.Contains(err.Error(), "not found") { | 		if !strings.Contains(err.Error(), "not found") { | ||||||
| 			return err | 			return errors.New(i18n.G("unable to delete tag %s: %s", tag, err)) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -546,7 +608,7 @@ func getLabelVersion(recipe recipe.Recipe, prompt bool) (string, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if initTag == "" { | 	if initTag == "" { | ||||||
| 		log.Fatal(i18n.G("unable to read version for %s from synced label. Did you try running \"abra recipe sync %s\" already?", recipe.Name, recipe.Name)) | 		return "", errors.New(i18n.G("unable to read version for %s from synced label. Did you try running \"abra recipe sync %s\" already?", recipe.Name, recipe.Name)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	log.Warn(i18n.G("discovered %s as currently synced recipe label", initTag)) | 	log.Warn(i18n.G("discovered %s as currently synced recipe label", initTag)) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user