private void ValidateVersion(ManifestData manifestData, Action <SemVersion, VersionTag> lifecycleVersionValidator)
        {
            // Check package version, make sure it's a valid SemVer string.
            SemVersion packageVersionNumber;

            if (!SemVersion.TryParse(manifestData.version, out packageVersionNumber))
            {
                AddError("In package.json, \"version\" needs to be a valid \"Semver\". {0}", ErrorDocumentation.GetLinkMessage(k_DocsFilePath, "version-needs-to-be-a-valid-semver"));
                return;
            }

            VersionTag versionTag;

            try
            {
                versionTag = VersionTag.Parse(packageVersionNumber.Prerelease);
            }
            catch (ArgumentException e)
            {
                AddError("In package.json, \"version\" doesn't follow our lifecycle rules. {0}. {1}", e.Message, ErrorDocumentation.GetLinkMessage(k_DocsFilePath, "version-is-invalid-tag-must-follow-lifecycle-rules"));
                return;
            }

            lifecycleVersionValidator(packageVersionNumber, versionTag);
            ValidateVersionAbilityToPromote(packageVersionNumber, versionTag, manifestData);
        }
        /**
         * Use this to know with package phase the version infers
         * However, if you need to know if this package is a release candidate, then use GetLifecyclePhaseOrRelation instead
         */
        internal static LifecyclePhase GetLifecyclePhase(string version)
        {
            SemVersion semVer = SemVersion.Parse(version);

            try
            {
                VersionTag pre = VersionTag.Parse(semVer.Prerelease);

                if (IsPreviewVersion(semVer, pre))
                {
                    return(LifecyclePhase.Preview);
                }
                if (IsReleasedVersion(semVer, pre))
                {
                    return(LifecyclePhase.Release);
                }
                if (IsExperimentalVersion(semVer, pre))
                {
                    return(LifecyclePhase.Experimental);
                }
                if (IsPreReleaseVersion(semVer, pre))
                {
                    return(LifecyclePhase.PreRelease);
                }
                return(LifecyclePhase.InvalidVersionTag);
            }
            catch (ArgumentException e)
            {
                if (e.Message.Contains("invalid version tag"))
                {
                    return(LifecyclePhase.InvalidVersionTag);
                }
                throw e;
            }
        }
        private void PreReleaseChecks(ManifestData currentManifest)
        {
            string errorMsg = String.Empty;

            if (Context.AllVersions != null)
            {
                SemVersion pkgVersion = SemVersion.Parse(currentManifest.version);
                // Get all versions that match x.y.z (so, any exp, preview, prerelease, etc).
                List <SemVersion> relatedVersions = pkgVersion.GetRelatedVersions(Context.AllVersions);

                // Get only the related previous versions
                SemVersion prevVersion = relatedVersions.Where(v => v <= pkgVersion).ToList().LastOrDefault();

                if (prevVersion != null)
                {
                    if (!PackageLifecyclePhase.IsPreReleaseVersion(prevVersion, VersionTag.Parse(prevVersion.Prerelease)))
                    {
                        errorMsg = string.Format(
                            "The previous version of this package ({0}) is not a Pre-Release. By Lifecycle V2 rules, a Pre-Release package can only be promoted automatically to production when the previous version is also a Pre-Release version. {1}",
                            prevVersion.ToString(),
                            ErrorDocumentation.GetLinkMessage(k_DocsFilePath,
                                                              "previous-version-of-this-package-is-not-a-pre-release-version"));
                    }
                    else
                    {
                        SemVersion lastPreVersion = relatedVersions.Where(v =>
                        {
                            VersionTag t = VersionTag.Parse(v.Prerelease);
                            return(PackageLifecyclePhase.IsPreReleaseVersion(v, t));
                        }).ToList().LastOrDefault();

                        if (lastPreVersion != null)
                        {
                            VersionTag lastTag = VersionTag.Parse(lastPreVersion.Prerelease);
                            VersionTag pkgTag  = VersionTag.Parse(pkgVersion.Prerelease);
                            if (pkgTag.Iteration <= lastTag.Iteration)
                            {
                                errorMsg = string.Format(
                                    "This package iteration ({0}) must be higher than the highest published iteration ({1}). Please update your package version to {2} {3}",
                                    pkgTag.Iteration,
                                    lastTag.Iteration,
                                    string.Format("{0}-{1}.{2}", pkgVersion.VersionOnly(), pkgTag.Tag,
                                                  lastTag.Iteration + 1),
                                    ErrorDocumentation.GetLinkMessage(k_DocsFilePath,
                                                                      "this-package-iteration-(x)-must-be-higher-than-the-highest-published-iteration-(y)"));
                            }
                        }
                    }
                }
                else
                {
                    errorMsg = string.Format(
                        "There is no previous Pre-Release version of this package available. By Lifecycle V2 rules, the first Pre-Release iteration of a new version needs to be approved and promoted by Release Management. Please contact Release Management to promote your package. {0}",
                        ErrorDocumentation.GetLinkMessage(k_DocsFilePath,
                                                          "previous-version-of-this-package-is-not-a-pre-release-version"));
                }
            }

            if (errorMsg != String.Empty)
            {
                AddPromotionConditionalError(errorMsg);
            }
        }