func runRelease()

in cmd/gorelease/gorelease.go [164:261]


func runRelease(ctx context.Context, w io.Writer, dir string, args []string) (success bool, err error) {
	// Validate arguments and flags. We'll print our own errors, since we want to
	// test without printing to stderr.
	fs := flag.NewFlagSet("gorelease", flag.ContinueOnError)
	fs.Usage = func() {}
	fs.SetOutput(ioutil.Discard)
	var baseOpt, releaseVersion string
	fs.StringVar(&baseOpt, "base", "", "previous version to compare against")
	fs.StringVar(&releaseVersion, "version", "", "proposed version to be released")
	if err := fs.Parse(args); err != nil {
		return false, &usageError{err: err}
	}

	if len(fs.Args()) > 0 {
		return false, usageErrorf("no arguments allowed")
	}

	if releaseVersion != "" {
		if semver.Build(releaseVersion) != "" {
			return false, usageErrorf("release version %q is not a canonical semantic version: build metadata is not supported", releaseVersion)
		}
		if c := semver.Canonical(releaseVersion); c != releaseVersion {
			return false, usageErrorf("release version %q is not a canonical semantic version", releaseVersion)
		}
	}

	var baseModPath, baseVersion string
	if at := strings.Index(baseOpt, "@"); at >= 0 {
		baseModPath = baseOpt[:at]
		baseVersion = baseOpt[at+1:]
	} else if dot, slash := strings.Index(baseOpt, "."), strings.Index(baseOpt, "/"); dot >= 0 && slash >= 0 && dot < slash {
		baseModPath = baseOpt
	} else {
		baseVersion = baseOpt
	}
	if baseModPath == "" {
		if baseVersion != "" && semver.Canonical(baseVersion) == baseVersion && releaseVersion != "" {
			if cmp := semver.Compare(baseOpt, releaseVersion); cmp == 0 {
				return false, usageErrorf("-base and -version must be different")
			} else if cmp > 0 {
				return false, usageErrorf("base version (%q) must be lower than release version (%q)", baseVersion, releaseVersion)
			}
		}
	} else if baseModPath != "" && baseVersion == "none" {
		return false, usageErrorf(`base version (%q) cannot have version "none" with explicit module path`, baseOpt)
	}

	// Find the local module and repository root directories.
	modRoot, err := findModuleRoot(dir)
	if err != nil {
		return false, err
	}
	repoRoot := findRepoRoot(modRoot)

	// Load packages for the version to be released from the local directory.
	release, err := loadLocalModule(ctx, modRoot, repoRoot, releaseVersion)
	if err != nil {
		return false, err
	}

	// Find the base version if there is one, download it, and load packages from
	// the module cache.
	var max string
	if baseModPath == "" {
		if baseVersion != "" && semver.Canonical(baseVersion) == baseVersion && module.Check(release.modPath, baseVersion) != nil {
			// Base version was specified, but it's not consistent with the release
			// module path, for example, the module path is example.com/m/v2, but
			// the user said -base=v1.0.0. Instead of making the user explicitly
			// specify the base module path, we'll adjust the major version suffix.
			prefix, _, _ := module.SplitPathVersion(release.modPath)
			major := semver.Major(baseVersion)
			if strings.HasPrefix(prefix, "gopkg.in/") {
				baseModPath = prefix + "." + semver.Major(baseVersion)
			} else if major >= "v2" {
				baseModPath = prefix + "/" + major
			} else {
				baseModPath = prefix
			}
		} else {
			baseModPath = release.modPath
			max = releaseVersion
		}
	}
	base, err := loadDownloadedModule(ctx, baseModPath, baseVersion, max)
	if err != nil {
		return false, err
	}

	// Compare packages and check for other issues.
	report, err := makeReleaseReport(ctx, base, release)
	if err != nil {
		return false, err
	}
	if _, err := fmt.Fprint(w, report.String()); err != nil {
		return false, err
	}
	return report.isSuccessful(), nil
}